summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>1997-12-02 02:31:05 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>1997-12-02 02:31:05 +0000
commit8d901c8263c0b8e3dcd4b7e7b1229ace8b8543c9 (patch)
treedd225a31ef2a6649522a7a4fe6ecbae4841a56d6
parent4a3c043af117eac7d312c92030fa7157f06cf85e (diff)
repository move of src/bin/pdksh to src/bin/ksh
-rw-r--r--bin/Makefile4
-rw-r--r--bin/pdksh/BUG-REPORTS1117
-rw-r--r--bin/pdksh/CONTRIBUTORS103
-rw-r--r--bin/pdksh/ChangeLog1071
-rw-r--r--bin/pdksh/ChangeLog.03589
-rw-r--r--bin/pdksh/IAFA-PACKAGE17
-rw-r--r--bin/pdksh/INSTALL151
-rw-r--r--bin/pdksh/LEGAL36
-rw-r--r--bin/pdksh/Makefile30
-rw-r--r--bin/pdksh/NEWS603
-rw-r--r--bin/pdksh/NOTES514
-rw-r--r--bin/pdksh/PROJECTS112
-rw-r--r--bin/pdksh/README190
-rw-r--r--bin/pdksh/alloc.c288
-rw-r--r--bin/pdksh/c_ksh.c1402
-rw-r--r--bin/pdksh/c_sh.c787
-rw-r--r--bin/pdksh/c_test.c616
-rw-r--r--bin/pdksh/c_test.h55
-rw-r--r--bin/pdksh/c_ulimit.c257
-rw-r--r--bin/pdksh/conf-end.h62
-rw-r--r--bin/pdksh/config.h351
-rw-r--r--bin/pdksh/edit.c1013
-rw-r--r--bin/pdksh/edit.h86
-rw-r--r--bin/pdksh/emacs-gen.sh44
-rw-r--r--bin/pdksh/emacs.c2182
-rw-r--r--bin/pdksh/eval.c1361
-rw-r--r--bin/pdksh/exec.c1671
-rw-r--r--bin/pdksh/expand.h106
-rw-r--r--bin/pdksh/expr.c596
-rw-r--r--bin/pdksh/history.c1193
-rw-r--r--bin/pdksh/io.c473
-rw-r--r--bin/pdksh/jobs.c1844
-rw-r--r--bin/pdksh/ksh.1tbl3298
-rw-r--r--bin/pdksh/ksh_dir.h26
-rw-r--r--bin/pdksh/ksh_limval.h24
-rw-r--r--bin/pdksh/ksh_stat.h59
-rw-r--r--bin/pdksh/ksh_time.h26
-rw-r--r--bin/pdksh/ksh_times.h20
-rw-r--r--bin/pdksh/ksh_wait.h51
-rw-r--r--bin/pdksh/lex.c1281
-rw-r--r--bin/pdksh/lex.h133
-rw-r--r--bin/pdksh/mail.c198
-rw-r--r--bin/pdksh/main.c820
-rw-r--r--bin/pdksh/misc.c1318
-rw-r--r--bin/pdksh/missing.c271
-rw-r--r--bin/pdksh/path.c346
-rw-r--r--bin/pdksh/proto.h292
-rw-r--r--bin/pdksh/sh.1tbl2372
-rw-r--r--bin/pdksh/sh.h707
-rw-r--r--bin/pdksh/shf.c1271
-rw-r--r--bin/pdksh/shf.h81
-rw-r--r--bin/pdksh/siglist.in56
-rw-r--r--bin/pdksh/siglist.sh42
-rw-r--r--bin/pdksh/syn.c948
-rw-r--r--bin/pdksh/table.c239
-rw-r--r--bin/pdksh/table.h176
-rw-r--r--bin/pdksh/tests/alias.t91
-rw-r--r--bin/pdksh/tests/arith.t79
-rw-r--r--bin/pdksh/tests/bksl-nl.t339
-rw-r--r--bin/pdksh/tests/brkcont.t195
-rw-r--r--bin/pdksh/tests/cdhist.t160
-rw-r--r--bin/pdksh/tests/eglob.t138
-rw-r--r--bin/pdksh/tests/glob.t96
-rw-r--r--bin/pdksh/tests/heredoc.t144
-rw-r--r--bin/pdksh/tests/history.t529
-rw-r--r--bin/pdksh/tests/ifs.t162
-rw-r--r--bin/pdksh/tests/integer.t218
-rw-r--r--bin/pdksh/tests/read.t56
-rw-r--r--bin/pdksh/tests/regress.t770
-rw-r--r--bin/pdksh/tests/th819
-rw-r--r--bin/pdksh/tests/th.sh28
-rw-r--r--bin/pdksh/tests/unclass1.t97
-rw-r--r--bin/pdksh/tests/unclass2.t166
-rw-r--r--bin/pdksh/tests/version.t8
-rw-r--r--bin/pdksh/trap.c432
-rw-r--r--bin/pdksh/tree.c656
-rw-r--r--bin/pdksh/tree.h137
-rw-r--r--bin/pdksh/tty.c179
-rw-r--r--bin/pdksh/tty.h109
-rw-r--r--bin/pdksh/var.c1137
-rw-r--r--bin/pdksh/version.c10
-rw-r--r--bin/pdksh/vi.c2174
-rw-r--r--distrib/alpha/inst-common/list6
-rw-r--r--distrib/alpha/ramdisk/raminst.conf8
-rw-r--r--distrib/arc/common/instbin-krb.conf8
-rw-r--r--distrib/arc/common/instbin.conf8
-rw-r--r--distrib/arc/ramdisk/list6
-rw-r--r--distrib/hp300/ramdisk/list3
-rw-r--r--distrib/hp300/ramdisk/raminst.conf8
-rw-r--r--distrib/i386/floppies/common/instbin-krb.conf8
-rw-r--r--distrib/i386/floppies/common/instbin.conf8
-rw-r--r--distrib/i386/floppies/ramdisk/instbin-nokrb.conf8
-rw-r--r--distrib/i386/floppies/ramdisk/instbin.conf8
-rw-r--r--distrib/i386/floppies/ramdisk/list4
-rw-r--r--distrib/miniroot/list6
-rw-r--r--distrib/mvme68k/ramdisk/raminst.conf6
-rw-r--r--distrib/powerpc/ramdisk/list6
-rw-r--r--distrib/ramdisk/list6
-rw-r--r--distrib/sets/lists/base/md.alpha343
-rw-r--r--distrib/sets/lists/base/md.i386777
-rw-r--r--distrib/sets/lists/base/md.mvme68k515
-rw-r--r--distrib/sets/lists/base/md.sparc535
-rw-r--r--distrib/sets/lists/base/mi77
-rw-r--r--distrib/sets/lists/man/mi27
-rw-r--r--distrib/sparc/floppies/inst-common/instbin-krb.conf8
-rw-r--r--distrib/sparc/floppies/inst-common/instbin.conf8
106 files changed, 399 insertions, 46906 deletions
diff --git a/bin/Makefile b/bin/Makefile
index ce509552c3a..28d2c50b65c 100644
--- a/bin/Makefile
+++ b/bin/Makefile
@@ -1,7 +1,7 @@
-# $OpenBSD: Makefile,v 1.7 1997/09/21 11:34:32 deraadt Exp $
+# $OpenBSD: Makefile,v 1.8 1997/12/02 02:27:16 deraadt Exp $
SUBDIR= cat chmod chio cp csh date dd df domainname echo ed expr hostname \
- kill ln ls md5 mkdir mt mv pax pdksh ps pwd rcp rm rmail rmdir \
+ kill ksh ln ls md5 mkdir mt mv pax ps pwd rcp rm rmail rmdir \
sleep stty sync test
.include <bsd.subdir.mk>
diff --git a/bin/pdksh/BUG-REPORTS b/bin/pdksh/BUG-REPORTS
deleted file mode 100644
index 1295a31fefb..00000000000
--- a/bin/pdksh/BUG-REPORTS
+++ /dev/null
@@ -1,1117 +0,0 @@
-$OpenBSD: BUG-REPORTS,v 1.5 1996/11/21 07:59:24 downsj Exp $
-
-List of reported problems (problems reported and fixed before 5.0.4 not
-included). Unresolved problems (may or may not still exist) marked by *,
-problems believed to be fixed marked by x.
-
-* pdksh 5.0.3, MIPS RISC/os 5.0 (bsd universe) (noted by Michael Rendell):
- for interactive, job controlled shells, the kernel's tty state gets twisted
- in such a way that all output is lost (eg, if ttyXX is wedged then
- "echo hi > /dev/ttyXX" from a seperate login appears to succeed but produces
- no output on ttyXX).
- Work around is to run a program and hit ^C.
-
-* pdksh 5.0.1, NetBSD 0.9a? (reported by Simon J. Gerraty): problem with
- job control not finding tty
- [from Mail.1:71]:
- Also, I have noticed (with 5.0.1 anyway) that if as root I su to a
- user I get:
- root:511$ su foobar
- warning: won't have full job control
- [1] + Stopped (tty output) stty erase ^?
- foobar:1$
-
-* pdksh 5.0.8, - (reported by Sean Hogan): attempting file name completion
- on a word with a single backquote causes a "no closing quote" error and
- loses the partially entered command (vi mode).
- [see Mail.2:48]
-
-* pdksh 5.0.10, - (reported by Andrew Moore): no overflow checking is done
- in integer parsing code.
- [see Mail.3:78]
-
-* pdksh 5.0.6+5.1.2, BSD43/MachTen (reported by Dan Menchaca): ksh freezes up
- terminal after a while after printing process exit message. 5.1.2 causes
- system to hang after executing two commands.
- [see Mail.3:96,5:42]
-
-* pdksh 5.1.3, - (reported by Brad Warkentin & others): if the last command of
- a pipeline is a shell builtin, it is not executed in the parent shell,
- so "echo a b | read foo bar" does not set foo and bar in the parent
- shell (at&t ksh will).
- [see Mail.7:32,Mail.9:65]
-
-* pdksh 5.1.3, - (reported by Gabor Zahemszky): emacs/vi doesn't have \ as quote
- character.
- [see Mail.7:87]
-
-* pdksh 5.1.3, - (reported by Gabor Zahemszky): emacs default bindings doesn't
- have vt52 arrow keys or vt100 alternate keypad mode bindings.
- [see Mail.7:87]
-
-* pdksh 5.1.3, SCO 3.2.2 (reported by Gabor Zahemszky): shell hangs
- waiting for finished process to finish.
- [see Mail.7:87]
-
-* pdksh 5.2.0, - (reported by Gabor Zahemszky): ^V in vi leaves cursor at
- start of the line.
- [see Mail.8:43]
-
-* enhancements that haven't been merged yet
- - Mail.6:36-39,78,84 recursive function diffs (add hard limit on
- depeth of recursion)
-
-* pdksh 5.2.3, - (reported by David Gast(? gast@twinsun.com)): history (fc,
- et al) don't work in shell scripts.
- [see Mail.10:49]
-
-* pdksh 5.2.4, - (reported by Gabor Zahemszky): echo ${foo[*]#/} generates
- bad substsitution error, newer ksh's don't (older ones do);
- error includes {...#@(/)}.
- [see Mail.XXX:XXX]
-
-* pdksh 5.2.4, - (reported by Gabor Zahemszky): emacs: ^P steps through
- multiline commands - should go to start of command.
- [see Mail.XXX:XXX]
-
-* pdksh 5.2.7, - (reported by Adrian Marsh): typeset -L20u xxx is ok is ksh88
- but not in pdksh.
- [see Mail.XXX:XXX]
-
-* pdksh 5.2.7, - (reported by Gabor Zahemszky): TMOUT doesn't effect
- select and read operations.
- [see Mail.XXX:XXX]
-
-* pdksh 5.2.8, - : extended pattern globing doesn't handle nested parens ().
-
-* pdksh 5.2.10, - (reported by Simon J. Gerraty): in emacs, <ESC><ESC> applied
- to a word with a macro does not complete the word (only expands the macro).
- [see Mail.XXX]
-
---------------------- put fixed problems below this line ---------------------
-
-x pdksh 5.0.3, NetBSD 0.9a (reported by Simon J. Gerraty): pipelines
- occasionally hang.
- [from Mail.1:71]:
- Yes, I just built 5.0.3 on zen (NetBSD) and the menu stuff worked fine.
- However I've just done:
-
- sjg:910$ diff -cb /etc/profile profile | more
-
- And it has been sitting there ever since.
- [... gdb output indicating process groups set up ok - presumed problem is
- with tty process group]
- [Fixed in 5.0.4 - do tcsetpgrp() in both parent and child for first process]
-
-x pdksh 5.0.2, ISC unix 3.01 (reported by Sean Hogan): set +o monitor (in
- interactive shell?) closes tty
- [from Mail.1:64]:
- I'm having two problems with the job control code, which I believe might
- be related. The first one is that "set +o monitor" closes the tty,
- which causes the shell to exit since its input is gone. According to
- the code, that would imply that FTALKING has mysteriously been turned
- off (jobs.c:343). But my understanding of the code is that FTALKING
- would only be clear for background processes, and set would be done by
- the shell. Do you have any insights here? It's not a big deal of course;
- I don't need to turn off monitor anyway.
- [fixed in 5.0.5 - problem was tty process group was being restored so
- shell could no longer read from tty]
-
-x pdksh 5.0.4, - (reported by Simon J. Gerraty and Sean Hogan):
- test "" -a x would fail.
- [fixed in 5.0.5 - t_wp being unnecessarily decremented in primary()]
-
-x pdksh 5.0.4, -: test -p foo would always fail.
- [fixed in 5.0.5 - spell S_ISFIFO correctly]
-
-x pdksh 5.0.4, -: test ! ! foo would generate error (unexpected !)
- [fixed in 5.0.5 - nexpr() always calls nexpr(), changes to posix code]
-
-x pdksh 5.0.4, -: set -i would generate an internal error.
- [fixed in 5.0.5 - use OF_SET in creating set_opts]
-
-x pdksh 5.0.4, -: let 0>22 would evaluate to true (and 0<22 false)
- [fixed in 5.0.5 - reversed order of O_LT and O_GT in enum]
-
-x pdksh 5.0.4, - (reported by Sean Hogan): echo does not process escape
- characters (ie, echo "foo\c" doesn't to the sysV thing)
- [see Mail.1:98]
- [fixed in 5.0.5 - echo now behaves like sysv echo]
-
-x pdksh 5.0.4, - (reported by Sean Hogan): tty process groups not restored
- properly (vi, :sh, exit causes vi to received SIGTTOU).
- [see Mail.1:98]
- [fixed in 5.0.5 - restore tty process group in j_exit]
-
-x pdksh 5.0.4, - (reported by Sean Hogan): the exit command does not do the
- stopped jobs check.
- [see Mail.1:94,95,98]
- [fixed in 5.0.5 - added LSHELL, hack c_exitreturn to use it]
-
-x pdksh 5.0.3, ISC unix 3.01 (reported by Sean Hogan): if notify is set,
- running cat & produces "[1] + Stopped (tty input) cat", but jobs, fg,
- etc. don't know about the job.
- [from Mail.1:76]
- I get [1] + Stopped (tty input) cat. Interestingly, "jobs" reports
- nothing, and "fg" doesn't see it either. But it's definitely there in
- the ps output. It only responds to kill -9, nothing else. I guess this
- is a side track?
- [see also Mail.1:97,Mail.2:2,3]
- [fixed in 5.0.6 - don't remove stopped jobs in the notify code of check_job()]
-
-x pdksh 5.0.5, - (reported by Sean Hogan): repeated history commands were being
- echoed after the command was executed.
- [see Mail.2:5,6]
- [fixed in 5.0.6 - call shf_flush() in case SHIST: of yylex()]
-
-x pdksh 5.0.5, -: wait with no arguments would hang forever.
- [fixed in 5.0.6 - only wait for running jobs in waitfor()]
-
-x pdksh 5.0.2, HP-UX 9.01 (reported by Sean Hogan): scipts occasionally get
- stopped with SIGTTIN
- [from Mail.1:68]:
- I noticed another small problem today, which is that occasionally
- (on an HP 9000/715, HP-UX 9.01, cc from the ANSI C developer set)
- a background process which is definitely not reading from its input
- stops with SIGTTIN. I first noticed this with a nohup'ed process, but
- it periodically happens without as well. The process is a perl script,
- if that makes any difference. Have you seen this on your HP(s)?
- [hasn't been seen in 5.0.3: Mail.1:73,76]
- [not a shell bug, see Mail.2:14,15]
-
-x pdksh 5.0.6, - (reported by Gordan Larson, Ed Ferguson): shell does not
- compile when VI isn't defined.
- [see Mail.2:22,40]
- [fixed in 5.0.7 - fixed up lex.c]
-
-x pdksh 5.0.6, - (reported by Gordan Larson): ksh.1 font typo.
- [see Mail.2:23]
- [fixed in 5.0.7]
-
-x pdksh 5.0.6, FreeBSd 1.1.5 (reported by Thomas Gellekum): CLK_TCK is defined
- to wrong value on FreeBSD; no depend target in Makefile; update /etc/shells
- in install target.
- [see Mail.2:28]
- [fixed in 5.0.7 - include <limits.h> in sh.h to get the right value; added
- depend target; print warning if ksh not in /etc/shells]
-
-x pdksh 5.0.6, - (reported by Michael Haardt): shell does not compile if JOBS
- not defined.
- [see Mail.2:32]
- [fixed in 5.0.7 - added ifdefs to jobs.c(check_job)]
-
-x pdksh 5.0.6, - (reported by Nick Holloway): exit status of command
- substitution is lost (known problem).
- [from Mail.2:33]:
- This is a variation on a theme of bug number 10 (and is one reason why
- currently ksh can not be used for Linux's MAKEDEV).
-
- The exit status from command substitution is not available when used with
- variable assignment.
-
- x=`false` && echo "Non-zero exit status lost".
- [fixed in 5.0.7 - instead of faking :, set rv to subst_exstat]
-
-x pdksh 5.0.7 - (reported by Sean Hogan): CMASK redefined in emacs.c
- [see Mail.2:44]
- [fixed in 5.0.8 changed CMASK to CHARMASK]
-
-x pdksh 5.0.7 - (reported by Sean Hogan): "r" (fc -e -) doesn't work.
- [see Mail.2:45]
- [fixed in 5.0.8 - increment wp, change strcmp() test]
-
-x pdksh 5.0.7 - (reported by Thomas Gellekum): make install typeo.
- [see Mail.2:46]
- [fixed in 5.0.8 - added missing $]
-
-x pdksh 5.0.8 - (reported by Sean Hogan): "FOO=bar exec blah" does not
- put FOO in environment.
- [see Mail.2:50]
- [fixed in 5.0.9 - re-arranged exec/command/builtin code in comexec()]
-
-x pdksh 5.0.8, QNX 4.2 (reported by Brian Campbell): "exec > /dev/null"
- generates an error.
- [see Mail.2:51]
- [see Mail.2.58 - caused by ambitious compiler using same label for c_exec()
- and c_builtin()]
- [fixed in 5.0.9 - c_exec() no longer an empty function.]
-
-x pdksh 5.0.8, - (reported by Brian Campbell): "echo a{b," prints a "Missing }"
- error - at&t ksh does not. at&t ksh always has brace-expansion on (unless
- set -o nogolob).
- [see Mail.2:51]
- [fixed in 5.0.9 - brace expansion now compatible with at&t ksh]
-
-x pdksh 5.0.8, - (reported by Sean Hogan): ulimit output garbled; syntax error
- in c_ulimit.c; no configure check for HAVE_SETRLIMIT.
- [see Mail.2:64]
- [fixed in 5.0.9 - use shprintf instead of shellf to print values; add
- setrlimit() check to configure]
-
-x pdksh 5.0.7, - (reported by Jan Djarv): `echo > /foo/bar' causes a script to
- exit - POSIX says it shouldn't.
- [see Mail.2:60]
- [fixed in 5.0.9 - iosetup returns error code, error messages cleaned up, etc]
-
-x pdksh 5.0.8, - : `more /etc/passwd &' followed by fg messes up tty settings.
- [fixed in 5.0.9 - only save new tty settings if job originally started in fg]
-
-x pdksh 5.0.9, - (reported by Andrew Moore): a blank line causes $? to be
- set to zero, newline after a here-document marker isn't read.
- [see Mail.3:5,6]
- [fixed in 5.0.10 - don't execute null trees, read the newline]
-
-x pdksh 5.0.9, - (reported by Michael Sullivan): mail checking reports you
- have mail, when there is only old mail.
- [fixed in 5.0.10 - use atime/mtime instead of size]
-
-x pdksh 5.0.9, - (reported by Chris Oates): if RANDOM is in ksh's environ
- when it starts, the shell dumps core.
- [see Mail.3:7,8]
- [fixed in 5.0.10 - var.c(typeset): free t->val.s instead of
- t->val.s + t->type]
-
-x pdksh 5.0.9, - (reported by Seah Hogan): ISC 3.01's make is confused by
- a backslash followed by a blank line.
- [see Mail.3:9,13]
- [fixed in 5.0.10 - changed make depend target to change blank lines to sh.h]
-
-x pdksh 5.0.9, - (reported by Andrew Moore): commands without a newline cause
- syntax errors - sh/ksh execute the commands.
- [see Mail.3:15]
- [fixed in 5.0.10 - have yyparse() accept newline and EOF]
-
-x pdksh 5.0.9, - (reported by Andrew Moore): empty arithmetic expressions not
- accepted.
- [see Mail.3:15,17]
- [fixed in 5.0.10 - v_evaluate(): if first token is END, changed to literal 0]
-
-x pdksh 5.0.9, - (reported by Andrew Moore): nulls in input are not ignored.
- [see Mail.3:15]
- [fixed in 5.0.10 - added strip_nuls() function and calls to it]
-
-x pdksh 5.0.9, - (reported by Andrew Moore): \241 (M-!) not passed through
- command substitutions.
- [see Mail.3:15]
- [fixed in 5.0.10 - evaluate(): cast c to a char before comparing to MAGIC]
-
-x pdksh 5.0.9, - (reported by Andrew Moore): newlines after here-documents
- are read twice; shell reports an error if newline is missing.
- [see Mail.3:25]
- [fixed in 5.0.10 - fixed up readhere()]
-
-x pdksh 5.0.9, - (reported with fix by Mike Jetzer): 'r r' repeats the r
- command forever.
- [see Mail.3:38]
- [fixed in 5.0.10 - start the search from the previous command]
-
-x pdksh 5.0.9, - (reported by Mike Jetzer): edit of multi-line commands
- does not result in single history entry.
- [see Mail.3:38]
- [fixed in 5.0.10 - use hist_append() to add second+ lines]
-
-x pdksh 5.0.9, - (reported by Dale DePriest): ksh_times.h uses BROKEN_TIMES
- [see Mail.3:43]
- [fixed in 5.0.10 - changed ksh_times.h]
-
-x pdksh 5.0.9, - (reported by J. T. Conklin): using [ instead of test is slow.
- [see Mail.3:46]
- [fixed in 5.0.10 - put in kludgy check for [ in eval.c(glob)]
-
-x pdksh 5.0.9, - (reported by Michael Haardt): signals do not interrupt
- read commands.
- [see Mail.3:20]
- [fixed in 5.0.10 - changed c_read() to check for fatal signals after EINTR]
-
-x pdksh 5.0.10, BSDI (reported by David Tamkin): use of _POSIX_VDISABLE in
- tty.h causes compiler error.
- [see Mail.3:67]
- [fixed in 5.0.10.1 - new variable vdisable_c set/used in edit.c]
-
-x pdksh 5.0.8, - (reported by Donald Craig): on systems with both union wait
- and waitpid(), waitpid() is passed a union wait pointer instead of an int
- pointer.
- [see Mail.2:54]
- [fixed in 5.1 - added ksh_waitpid() define; cast status arg as needed.]
-
-x pdksh 5.0.10, - (reported by David Tamkin): space in vi command mode does
- nothing.
- [see Mail.3:76]
- [fixed in 5.1 - vi.c(classify[]) table got changed by accident.]
-
-x pdksh 5.0.10, - (reported by Danial Quinlan): forward-word and
- delete-word-forward functions in emacs don't go to the right place.
- [see Mail.3:79]
- [Fixed in 5.1 - changed order of loops in emacs.c(x_fword())]
-
-x pdksh 5.0.10, - (reported by David Tamkin): eof in multiline command
- causes shell to exit, even if ignoreeof is set.
- [see Mail.3:76]
- [Fixed in 5.1 - reset eof after longjmp() in main.c(shell)]
-
-x pdksh 5.0.9, Ultrix 4.2 (reported by Matthew Nethook): type-ahead while
- shell is waiting for a command to finish is temporarily lost until a
- program that reads from stdin or goes a stty/gtty is run.
- [see Mail.3:61,62]
- [Fixed in 5.1 - changed aclocal.m4 to not define HAVE_TERMIOS_H on ultrix]
-
-x pdksh 5.0.10, - (reported by David Tamkin): if INT is trapped, ^C in
- vi/emacs won't flush buffer/re-issue new prompt.
- [see Mail.3:5,76]
- [Fixed in 5.1 - use unwind() in vi/emacs to get back to shell()]
-
-x pdksh 5.0.10, - (reported by Dale DePriest): in emacs mode, file completions
- resulting in long names (>256) cause core dumps
- [see Mail.3:72]
- [Fixed in 5.1 - use dynamically sized buffers in emacs code]
-
-x pdksh 5.0.10, - (reported by Dale DePriest): in emacs mode, command
- completions (^[=) resulting in multiple hits caused internal memory error.
- [see Mail.4:8]
- [Fixed in 5.1 - don't call list_stash() twice in compl_command]
-
-x pdksh 5.0.10, - (reported by Dave Hatton): autoloading functions fail
- on the first attempt, then work.
- [see Mail.4:10]
- [Fixed in 5.1 - in findcom(), check for include() returning non-0 (was 0)]
-
-x pdksh 5.0.10, - (reported by Art Pina via Dale DePriest): when SECONDS
- parameter is assigned, it always acts as if 0 were assigned.
- [see Mail.4:12]
- [Fixed in 5.1 - set internal seconds variable to time - assigned value]
-
-x pdksh 5.1.0 - (reported by Larry Bouzane): for/select loops don't allow
- {..} to be used instead of do...done.
- [see Mail.4:16]
- [Fixed in 5.1.1 - changed syn.c(dogroup) to allow {/} instead of do/done]
-
-x pdksh 5.1.0 - (reported by Andrew Moore and Larry Bouzane): a command ending
- in ; or & that is not followed by a newline causes a syntax error.
- [see Mail.4:126,128]
- [Fixed in 5.1.1 - don't call syntaxerr() in get_command() if EOF is read]
-
-x pdksh 5.1.0, - (reported by Simon J. Gerraty): ksh died reading history
- file (complex history, in hist_skip_backup()).
- [see Mail.4:24]
- [Fixed in 5.1.1 - hist_skip_back(): don't start past the end of the buffer]
-
-x pdksh 5.1.0 BSDI 1.1 (reported by Karl Denninger): after receipt of SIGHUP,
- shell waits for foreground process to complete.
- [see Mail.4:50,57]
- [Fixed in 5.1.1 - added fatal_trap flag, check in jobs.c(j_waitj)]
-
-x pdksh 5.1.0 - (reported by Bob Manson): a leading non-white-space IFS
- character does cause a field to be delimited.
- [see Mail.4:68]
- [Fixed in 5.1.2 - changed expand() to do the right thing.]
-
-x pdksh 5.1.2, -: ^c during $ENV or .profile kills shell; should just go
- to prompt.
- [see Mail.5:14]
- [fixed in 5.2.4 - added intr_ok flag to main.c(include)]
-
-x pdksh 5.1.2, - (reported by Dan Quinlan): when shell prints out
- execution trees (typeset -f), if botches elif statements.
- [see Mail.5:17]
- [fixed in 5.1.3 - changed tree.c(ptree) to deal with elif.]
-
-x pdksh 5.1.2, - (reported by Dale DePriest): fc -l -- -40 fails if there
- are fewer than 40 commands.
- [see Mail.5:19]
- [fixed in 5.1.3 - changed history.c(histget) to allow out of range numbers]
-
-x pdksh 5.1.2, - (reported by Art Mills): file completion in command mode
- doesn't work on a single character.
- [see Mail.5:13]
- [fixed in 5.1.3 - in vi.c(vi_cmd) call complete_word() with 1 not 0]
-
-x pdksh 5.1.2, - (reported by Dan Quinlan): an error in a let statement
- causes shell to exit function/script. at&t ksh just prints error and
- returns from let.
- [see Mail.5:17]
- [fixed in 5.2.3 - added error_ok arg to evaluate() and v_evaluate()]
-
-x pdksh 5.1.2, - (reported by Art Mills): if markdirs option is set, file
- completion in vi adds two slashes to directories.
- [see Mail.5:35]
- [fixed in 5.1.3 - vi.c(complete_word), don't add / if file ends in one]
-
-x pdksh 5.1.2, - (reported by Dale DePriest): history read from history file
- have negitive numbers and can't be accessed (fc thinks neg numbers are
- relative).
- [see Mail.5:39]
- [fixed in 5.1.3 - EASY_HISTORY/hist_init: increment line for each line]
-
-x pdksh 5.1.2, - (reported by David Tamkin): FPATH isn't searched if PATH
- search can't find command (undocumented at&t ksh feature).
- [see Mail.5:45]
- [fixed in 5.1.3 - exec.c(findcom) search FPATH if PATH search fails]
-
-x pdksh 5.1.2, - (reported by Dan Quinlan): output typeset -f isn't
- very pretty (no indenting done).
- [see Mail.5:17]
- [fixed in 5.1.3 - indenting added to ptree routines]
-
-x pdksh 5.0.9, ISC 3.2 (reported by cobra@guarany.cpd.unb.br): Running the
- following script with pdksh crashes the machine:
- cat > /tmp/foobar
- The same command in an interactive pdksh does not cause a crash.
- [see Mail.3:21,Mail.5:62]
- [Fixed by Interactive - it is caused by an OS bug for which there is a patch]
-
-x pdksh 5.1.3, linux - (reported by Dan Quinlan): doesn't compile under new
- linux due to declaration conflict between basename() in unistd.h and
- pdksh'd basename.
- [see Mail.5:90]
- [fixed in 5.2.0 - changed basename() to arrayname()]
-
-x pdksh 5.1.3, - (reported by William Hudacek): very long prompts cause
- vi command line editor grief.
- [see Mail.6:2]
- [fixed in 5.2.0 - initial part of prompt is stripped if its too long]
-
-x pdksh 5.1.3, - (reported by Roberto Zacheo): when set -u, variable trimming
- with always causes an error.
- [see Mail.6:21]
- [fixed in 5.2.0 - fixed varsub() to test if variable is null]
-
-x pdksh 5.1.3, - (reported by David Tamkin): when a fucntion is autoloaded,
- ksh complains the definition file didn't define the function, even if it did.
- [see Mail.6:52]
- [fixed in 5.2.0 - exec.c(comexec): when checking if defined, use cp,
-
-x pdksh 5.1.3, ICS unix 3.2 (reported by Robert Clark): auto configuration
- test for memmove doesn't work
- [see Mail.6:65]
- [fixed in 5.2.0 - special cases added for memmove, bcopy, memset]
-
-x pdksh 5.1.3, Unixware (Intel-SVR4.2) (reported by Thanh Ma): auto
- configuration test for memset doesn't work; same for rlimit type.
- [see Mail.6:67]
- [fixed in 5.2.0 - special cases added for memmove, bcopy, memset; rlim_t
- configuration stuff re-arranged]
-
-x pdksh 5.1.3, - (reported by Mike Jetzer + fix): . in vi doesn't work
- after history motion or after one command is completed and another is being
- edited.
- [see Mail.6:85]
- [fixed in 5.2.0 - fix up classify table, special case for empty initial
- insert]
-
-x pdksh 5.1.3, - Janjaap van Velthooven: ^v (version) missing in vi mode.
- [see Mail.6:98]
- [fixed in 5.2.0 - added]
-
-x pdksh 5.1.3, - : y% on or before right bracket/paren/brace doesn't yank the
- brackets - just what is in the brackets...
- [fixed in 5.2.0 - changes to vi.c(domove,vi_cmd)]
-
-x pdksh 5.1.3, - (reported by Rob Mayoff): [[ ]] command doesn't do lazy
- evaluation.
- [see Mail.7:2]
- [fixed in 5.2.1 - test routines re-arranged to deal with this]
-
-x pdksh 5.1.3, - (reported by Will Renkel): "r | more" doesn't work (nothing
- is sent to more).
- [see Mail.7:13]
- [fixed in 5.2.0 - history commands now done in c_fc, not pushed onto input
- stack]
-
-x pdksh 5.1.3, - (reported by Rod Byrne, John Rochester): if a program leaves
- the non-blocking (O_NONBLOCK) flag set after it exists, the shell
- exits (multiple eofs).
- [see Mail.7:15,16,51]
- [fixed in 5.2.0: O_NONBLOCK is reset if read fails with EAGAIN,EWOULDBLOCK]
-
-x pdksh 5.1.3, - (reported by Dale DePriest + fix): emacs: can't delete chars
- from pattern in incremental search mode.
- [see Mail.7:17]
- [fixed in 5.2.0 - handle it]
-
-x pdksh 5.1.3, Linux 1.2.2 (reported by Fritz Heinrichmeyer + fix): siglist.sh
- doesn't work due to bug in bash 1.4.3 (trap is called incorrectly in
- subshell causing temp file to be removed prematurely).
- [see Mail.7:21]
- [fixed in 5.2.0 - clear all traps in subshell so file isn't removed]
-
-x pdksh 5.1.3, - (reported by Dale DePriest + fix): emacs: can't prefix
- commands with more than single digit; many commands don't use nnumber
- prefix.
- [see Mail.7:26,40]
- [fixed in 5.2.0 - x_set_arg reads sequence of numbers, other commands
- changed to use x_arg]
-
-x pdksh 5.1.3, - (reported by Dale DePriest): fc command line parsing
- (and its interaction with history alias) doesn't act like at&t ksh:
- history -40 gives bad option 4 error.
- [see Mail.7:41,49]
- [fixed in 5.2.1 - kludge parsing of -40 (numbers are option letters)]
-
-x pdksh 5.1.3, - (reported by Dale DePriest): if PS1 contains paramaters that
- get expanded, and if those parameters contain any ! characters, the !'s get
- changed to history numbers.
- [see Mail.7:44]
- [fixed in 5.2.0 - substitution done after ! and !! substitution]
-
-x pdksh 5.1.3, - (reported by Steve Wallis): set -a (set -o allexport) has
- no effect.
- [see Mail.7:47]
- [fixed in 5.2.0 - changes to c_read, c_getopts, and comexec]
-
-x pdksh 5.1.3, - (reported by Alexander S. Jones): (sleep 10000&) waits for
- the sleep to complete.
- [see Mail.7:54]
- [fixed in 5.2.0 - execute() case TASYNC clears EXEC flag in call to execute]
-
-x pdksh 5.1.3, - (reported by Will Renkel): positional parameters can't be
- accessed within temporary variable assignments (eg, "FOO=$1 blah" doesn't
- set FOO to $1.
- [see Mail.7:57]
- [fixed in 5.2.0 - var.c(newblock) - copy argc/argv from previous environment]
-
-x pdksh 5.1.3, SCO unix ? (reported by Sean Hogan): job control stuff doesn't
- work as sco doesn't do job control operations on /dev/tty.
- [see Mail.7:30,43,69,70,74]
- [fixed in 5.2.0 - don't try opening /dev/tty if on SCO]
-
-x pdksh 5.1.3, - (reported with fix by Mike Jetzer): vi globing tacks
- * at the end of files even if there are globing chars in last component
- of filename (at&t ksh does not).
- [see Mail.7:71]
- [fixed in 5.2.0 - don't append * if there are unescaped globing chars]
-
-x pdksh 5.1.3, - (reported with fix by Gabor Zahemszky): typoes in acconfig.h,
- sh.h uses SVR3_PGRP insteda of SYSV_PGRP.
- [see Mail.7:87]
- [fixed in 5.2.0]
-
-x pdksh 5.1.3, - (reported by Gabor Zahemszky): emacs doesn't have ^[^].
- [see Mail.7:87]
- [fixed in 5.2.0 - added search-char-backward]
-
-x pdksh 5.2.0, - (reported by David Tamkin): pwd -P doesn't strip .. and .
- properly.
- [see Mail.7:98]
- [fixed in 5.2.0 - include ksh_stat.h in c_ksh.c]
-
-x pdksh 5.2.0, - (reported by Dale DePriest): unistd.h config test
- doesn't include sys/types before dirent.h.
- [see Mail.8:2]
- [fixed in 5.2.0]
-
-x pdksh 5.2.0, - (reported by Robert Gallant): emacs file/command completion
- code can clobber memory.
- [see Mail.8:11]
- [fixed in 5.2.1 - wrong variable being checked in buffer growing in
- emacs.c(compl_file,compl_command)]
-
-x pdksh 5.2.0, - (reported by David Tamkin): when CDPATH set and cd'ing to a
- directory that doesn't exist, the error message contains the last element
- of the CDPATH.
- [see Mail.8:8]
- [fixed in 5.2.0 - fixed error message]
-
-x pdksh 5.2.0, - (reported by David Tamkin): if PS1 has an error in it
- (eg, parameter expansion error), the shell loops forever printing
- the error.
- [see Mail.8:32]
- [fixed in 5.2.3 - create error handling environment while expanding PS1]
-
-x pdksh 5.2.0, Coherent machines (reported by Gabor Zahemszky): insert after
- movement in emacs mode replaces all chars with first char on line.
- System's bcopy doesn't handle overlapping src/dst.
- [see Mail.8:38,43]
- [fixed in 5.2.1 - check for broken memmove/bcopy in aclocal.m4]
-
-x pdksh 5.2.0, - (reported by Gabor Zahemszky): ^[= in vi prints empty
- strings for directory matches if markdirs is set.
- [see Mail.8:48]
- [fixed in 5.2.1 - skip trailing /'s before looking for last /]
-
-x pdksh 5.2.0, - (reported by Gabor Zahemszky): <ESC>^H bound to del-back-char
- not del-back-word
- [see Mail.8:50-52]
- [fixed in 5.2.1 - fixed x_emacs_keys]
-
-x pdksh 5.2.1, - (reported by David Tamkin): compile fails due to lack
- of c_test.h
- [see Mail.8:58]
- [fixed in 5.2.2 - fixed put c_test.h in distribution]
-
-x pdksh 5.2.2, - (reported by Simon J. Gerraty): hist_source not being
- initialized in complex history.
- [see Mail.8:64]
- [fixed in 5.2.3 - set it in second hist_init()]
-
-x pdksh 5.2.2, - (reported by Gabor Zahemszky): set -A does not reset
- the array contents.
- [see Mail.8:65]
- [fixed in 5.2.3 - changed var.c(unset) to unset whole array if appropriate]
-
-x pdksh 5.2.2, - (reported by Gabor Zahemszky): getopts stops after an error;
- at&t ksh carries on with next option.
- [see Mail.8:65]
- [fixed in 5.2.3 - remove GI_DONE flag from ksh_getopt()]
-
-x pdksh 5.2.2, - (reported by Gabor Zahemszky): getopts prints shell name
- twice in error messages.
- [see Mail.8:65]
- [fixed in 5.2.3 - added GI_NONAME flag]
-
-x pdksh 5.2.2, - (reported by Gabor Zahemszky): pdksh's test doesn't know about
- /dev/fd/n.
- [see Mail.8:65]
- [fixed in 5.2.3 - added test_stat() and test_eaccess()]
-
-x pdksh 5.2.2, - (reported by Thomas Gellekum): config test for memmove/bcopy
- missing semi-colon
- [see Mail.8:67]
- [fixed in 5.2.3]
-
-x pdksh 5.2.2, - (reported by Donald Craig): fc string doesn't find string
- if it is the most recent command.
- [see Mail.8:76]
- [fixed in 5.2.3 - fixed off by one error in history.c(hist_get)]
-
-x pdksh 5.2.2, - (reported by Gabor Zahemszky): pdksh doesn't do the
- "You have running jobs" when user attempts to log out.
- [see Mail.8:74]
- [fixed in 5.2.3 - added set -o nohup option with supporting code]
-
-x pdksh 5.2.2, - (reported by Gabor Zahemszky): configure test for
- broken memmove/bcopy doesn't work.
- [see Mail.8:93]
- [fixed in 5.2.3 - fixed test to copy overlapping buffers]
-
-x pdksh 5.1.3, - (reported by <wendt@sv5.mch.sni.de>): doesn't compile on
- solaris 5.x with COMPLEX_HISTORY defined.
- [see Mail.8:98]
- [fixed in 5.2.3 - undef COMPLEX_HISTORY if flock not available]
-
-x pdksh 5.2.2, - (reported by Gabor Zahemszky): tilde expansion not preformed
- in word part of ${foo[-+=?} substitution.
- [see Mail.9:7]
- [fixed in 5.2.3 - allow ~foo to end in a close brace]
-
-x pdksh 5.2.2, - (reported by Gabor Zahemszky): "fc 30" edits from 30 to
- most recent history (should be just 30).
- [see Mail.9:7]
- [fixed in 5.2.3 - if !-l and no last given, use first]
-
-x pdksh 5.2.2, - (reported by Gabor Zahemszky): [many problems with man page]
- [see Mail.9:12]
- [fixed in 5.2.3 - fixed problems]
-
-x pdksh 5.2.2, - (reported by Gabor Zahemszky): #else followed by non-comment
- in sigact.c.
- [see Mail.9:13]
- [fixed in 5.2.3 - turn it into a comment]
-
-x pdksh 5.2.2, - (reported with fix by Gabor Zahemszky): two argument form of
- cd doesn't work.
- [see Mail.9:14]
- [fixed in 5.2.3 - in c_cd(), use current_wd not path]
-
-x pdksh 5.2.2, - (reported with fix by Gabor Zahemszky): command -V doesn't
- report reserved words.
- [see Mail.9:30]
- [fixed in 5.2.3 - in c_whence(), look for reserved words if vflag set]
-
-x pdksh 5.2.3, - (reported by Dale DePriest): at&t's tbl wants space
- between font specification and end of table descrption (ie, fB . not
- fB.).
- [see Mail.9:41]
- [fixed in 5.2.4 - put spaces in]
-
-x pdksh 5.2.3, - (reported by David Tamkin & Claus L{gel Rasmussen): PS1
- isn't imported from environment anymore.
- [see Mail.9:43,76]
- [fixed in 5.2.4 - main: don't set PS1 if it is already set]
-
-x pdksh 5.2.3, - (reported by Gary Rafe): If PS1 contains newlines, vi
- editing mode dones't redraw lines properly.
- [see Mail.9:63]
- [fixed in 5.2.4 - added prompt_skip stuff to vi/emacs]
-
-x pdksh 5.2.3, - (reported & fixed by Mike Jetzer): cd: error message if
- directory didn't exist was wrong.
- [see Mail.9:66]
- [fixed in 5.2.4 - print correct string in error message]
-
-x pdksh 5.2.3, - (reported & fixed by Mike Jetzer): vi: <ESC>* shouldn't append
- a * if word contains a $.
- [see Mail.9:66]
- [fixed in 5.2.4 - vi.c(glob_word): check for $ in word, check for null
- expansion]
-
-x pdksh 5.2.3, - (reported & fixed by Mike Jetzer): vi: <ESC>= doesn't
- list expansions in column form.
- [see Mail.9:66]
- [fixed in 5.2.4 - use pr_menu to print things nicely]
-
-x pdksh 5.2.3, - (reported Larry Bouzane): should be a way of installing
- binary/man page as pdksh instead of ksh.
- [see Mail.9:100]
- [fixed in 5.2.4 - use the --enable-shell=pdksh option to configure]
-
-x pdksh 5.2.3, - (reported by Gabor Zahemszky): [many problems with man
- page]
- [see Mail.10:20]
- [fixed in 5.2.4 - fixed problems]
-
-x pdksh 5.2.3, - (reported by Gabor Zahemszky): exec 1<&9 reports
- error with ">&9" in it.
- [see Mail.10:20]
- [fixed in 5.2.4 - changed iosetup()]
-
-x pdksh 5.2.3, - (reported by Gabor Zahemszky): man page doesn't document
- /dev/fd/N
- [see Mail.10:20]
- [fixed in 5.2.4 - updated manual]
-
-x pdksh 5.2.3, - (reported by Ted Coady): [[ foo/bar = foo* ]]
- fails; should succeed.
- [see Mail.10:32]
- [fixed in 5.2.4 - fixed problem in exec.c(dbteste_getopnd)]
-
-x pdksh 5.2.3, - (reported by Ruei-wun Tu): make on NeXT/NeXTSTEP 3.3
- doesn't understand .PRECIOUS target and so does nothing.
- [see Mail.10:43]
- [fixed in 5.2.4 - moved .PRECIOUS after all in Makefile.in]
-
-x pdksh 5.2.3, - (reported & fixed by Paul Borman): shell doesn't kill
- foreground process when SIGHUP received; Also, CONT sent before HUP.
- [see Mail.10:44]
- [fixed in 5.2.4 - j_exit now sends HUP to foreground process]
-
-x pdksh 5.2.3, AIX 3.2.5 (reported by Ian Portsmouth): C compiler compains
- about sigtraps[] being re-declared in trap.c.
- [see Mail.10:73]
- [fixed in 5.2.4 - use cpp define to avoid bogus re-declaration error]
-
-x pdksh 5.2.3, - (reported by Michael Haardt): ENV should not be
- included if shell is compiled as sh and posix option not set.
- [see Mail.10:83]
- [fixed in 5.2.4 - only include ENV if POSIX, if compiled as sh]
-
-x pdksh 5.2.3, - (reported & fixed by DaviD W. Sanderson): case statements
- don't allow {/} in place of IN/ESAC.
- [see Mail.10:77,78]
- [fixed in 5.2.4 - allow {/} in case statements]
-
-x pdksh 5.2.3, - (reported by Larry Daffner): $? is incorrectly zero'd
- at start of traps.
- [see Mail.11:9]
- [fixed in 5.2.4 - don't clear exstat in main.c(shell)]
-
-x pdksh 5.2.3, - (reported by Frank "Crash" Edwards): configure on linux XXX
- doesn't detect the presence of lstat().
- [see Mail.11:36]
- [fixed in 5.2.4 - change configure to include <sys/stat.h> in lstat() test]
-
-x pdksh 5.2.3, - (reported by Gabor Zahemszky): typeset -f dumps core
- in the after using autoload functions.
- [see Mail.11:74?]
- [fixed in 5.2.4 - c_typeset no longer traverses the array link for functions]
-
-x pdksh 5.2.3, - (reported by Gabor Zahemszky): typeset -f does not report
- undefined autoload functions
- [see Mail.11:74?]
- [fixed in 5.2.4 - c_typeset: don't ignore unset functions]
-
-x pdksh 5.2.3, - (reported by Dale DePriest): alias -t -r does not
- reset aliases.
- [see Mail.11:99]
- [fixed in 5.2.4 - c_alias: call ksh_getopt_reset() before calling c_unalias]
-
-x pdksh 5.2.3, - (reported & fixed by Jason Tyler): 'echo abc^Jfc -e - a=b e'
- echos b, not bbc.
- [see Mail.11:100?]
- [fixed in 5.2.4 - hist_replace: use s, not last]
-
-x pdksh 5.2.3, - (reported by Jason Tyler): 'fc -e -' when there is
- no history causes infinite loop.
- [see Mail.11:100?]
- [fixed in 5.2.4 - histbackup: allow histptr to go below history]
-
-x pdksh 5.2.4, - (reported by David Tamkin): jmp_buf is used instead of
- sigjmp_buf.
- [see Mail.XXX:XXX]
- [fixed in 5.2.5 - added ksh_jmp_buf and defined appropriately]
-
-x pdksh 5.2.4, - (reported by Stephen Coffin): /<RETURN> in vi mode does not
- repeat last search.
- [see Mail.XXX:XXX]
- [fixed in 5.2.5 - vi.c(vi_hook) - make it repeat last search]
-
-x pdksh 5.2.4, - (reported by Gabor Zahemszky): functions containing select
- commands aren't printed correctly by typeset.
- [see Mail.XXX:XXX]
- [fixed in 5.2.5 - tree.c(ptree) - add case for TSELECT]
-
-x pdksh 5.2.4, - (reported & fixed by Stefan Dalibor): COLUMNS isn't set on
- shell start up (and window size is ignored) 'cause tty_fd isn't valid when
- x_init() is called.
- [see Mail.XXX:XXX]
- [fixed in 5.2.5 - call x_init() after j_init() is called]
-
-x pdksh 5.2.4, - (reported by Will Renkel): "echo -" just prints a blank
- line - should print the minus.
- [see Mail.XXX:XXX]
- [fixed in 5.2.5 - c_ksh.c(c_print): don't do argument parsing on lone -]
-
-x pdksh 5.1.3, - (reported by Gabor Zahemszky): emacs doesn't have ^[*.
- [see Mail.7:87]
- [fixed in 5.2.5]
-
-x pdksh 5.2.3, - (reported by Mike Jetzer): in vi, <ESC>= doesn't append
- a / after directories.
- [see Mail.9:66]
- [fixed in 5.2.5]
-
-x pdksh 5.2.0, - (reported by Gabor Zahemszky): can set readonly variables
- via command assignments (eg, "readonly x=y; x=z /bin/echo hi" should
- fail and doesn't).
- [see Mail.8:50,65]
- [fixed in 5.2.5 - LOCAL_COPY flag passed from comexec() down to local()]
-
-x pdksh 5.2.4, - (reported by Tom Karches): history: "r old=new", with
- no commands prefix given, prints "fc: too mnay arguments" - it should
- do the subst on the previous command.
- [see Mail.XXX:XXX]
- [fixed in 5.2.5]
-
-x pdksh 5.2.3, - (reported by Vigen Pogosyan): assignments in $(( ... ))
- remember the base that was assigned in pdksh - does not in at&t ksh.
- [see Mail.10:54]
- [fixed in 5.2.5: uset setint() in expr.c(evalexpr)]
-
-x pdksh 5.2.4, - (reported by Gabor Zahemszky): emacs: ^O steps down
- two lines (should be 1).
- [see Mail.XXX:XXX]
- [fixed in 5.2.5: convert history line to command number, then convert back]
-
-x pdksh 5.2.3, - (reported by David Gast(? gast@twinsun.com)): fc -ln -1 -1
- reports the current command, not the previous command.
- [see Mail.10:49]
- [fixed in 5.2.5]
-
-x pdksh 5.2.3, - (reported by Matthew Green): foo=`^Jecho bar` doesn't
- set foo to bar (foo is empty).
- [see Mail.XXX:XXX]
- [fixed in 5.2.5: syn.c: set multiline.on when source is SSTRING]
-
-x pdksh 5.2.5, - (reported by Gabor Zahemszky): continue/break: if n
- is too big, shell prints internal error message.
- [see Mail.XXX:XXX]
- [fixed in 5.2.6: fix c_brkcont to use last loop if n is too big]
-
-x pdksh 5.2.5, - (reported by Gabor Zahemszky): set: +o in ksh93
- prints command that sets various options.
- [see Mail.XXX:XXX]
- [fixed in 5.2.6: changed misc.c(printoptions)]
-
-x pdksh 5.2.5, - (reported by Gabor Zahemszky): COLUMNS/LINES variables
- are not exported.
- [see Mail.XXX:XXX]
- [fixed in 5.2.6: use typeset() in edit.c(x_init) to export COLUMNS/LINES]
-
-x pdksh 5.2.5, - (reported by Gabor Zahemszky): emacs: <ESC><ESC> puts
- space after completed directories.
- [see Mail.XXX:XXX]
- [fixed in 5.2.6: check for single/non-directory match in emacs.c(do_complete)]
-
-x pdksh 5.2.5, - (reported by Gabor Zahemszky): vi: # removes comment
- and executes if command already commented.
- [see Mail.XXX:XXX]
- [fixed in 5.2.6: added vi.c(do_comment)]
-
-x pdksh 5.2.7, - (reported by Adrian Marsh): test doesn't have == operator.
- [see Mail.XXX:XXX]
- [fixed in 5.2.8: added == to c_test.c operator table]
-
-x pdksh 5.2.7, - (reported by Mike Jetzer): pdksh sets/exports COLUMNS/LINES
- which causes applications not to respond to window size changes.
- [see Mail.XXX:XXX]
- [fixed in 5.2.8: COLUMNS/LINES no longer exported automatically]
-
-x pdksh 5.2.7, - (reported by Gabor Zahemszky): getopts sets OPTIND differently
- that at&t ksh when a bad option is given.
- [see Mail.XXX:XXX]
- [fixed in 5.2.8: OPTIND not set if option was bad - fragile fix - may go away]
-
-x pdksh 5.2.7, - (reported with fix by Marc Olzheim): sh version shouldn't
- have mail check stuff, macro expansion in PS[0-9].
- [fixed in 5.2.8: added lots of ifdefs]
-
-x pdksh 5.2.7, - (reported by Gabor Zahemszky): sub commands in PS1 cause
- a warning message to be printed.
- [see Mail.XXX:XXX]
- [fixed in 5.2.8: lex.c(set_prompt) - don't print the warning message]
-
-x pdksh 5.2.7, - (reported by Tom Watson): some environment variables
- (eg, PATH) are converted to uppercase on 16-bit int machine.
- [see Mail.XXX:XXX]
- [fixed in 5.2.8: struct tbl.flag (32 bit thing) was being treated as an
- int in some places]
-
-x pdksh 5.2.7, - (reported by Gabor Zahemszky): unset always returns 0 - should
- return 1 if variable/function is not set.
- [see Mail.XXX:XXX]
- [fixed in 5.2.8: fixed c_sh.c(c_unset)]
-
-x pdksh 5.2.7, - (reported by Gabor Zahemszky): select should only print the
- menu the first time, if REPLAY is empty, or if a blank line is entered.
- [see Mail.XXX:XXX]
- [fixed in 5.2.8: fixed up exec.c(execute,do_selectargs)]
-
-x pdksh 5.2.7, - (reported by Gabor Zahemszky): shell reports "cannot execute"
- error if file exists, even if . not in path.
- [see Mail.XXX:XXX]
- [fixed in 5.2.8: fixed up exec.c(comexec)]
-
-x pdksh 5.1.3, - (reported with partial fix by ra@rhi.hi.is): shell doesn't
- listen to sigwinch.
- [see Mail.7:7 and related]
- [fixed in 5.2.8: changed edit.c(x_init) to catch sigwinch]
-
-x pdksh 5.2.7, - (reported by Gabor Zahemszky): typeset doesn't report
- variables that have attributes (like export) but no values.
- [see Mail.XXX:XXX]
- [fixed in 5.2.8: fixed up c_ksh.c(c_typeset)]
-
-x pdksh 5.2.7, - (reported by Gabor Zahemszky): error message printed as
- a result of "set -o nounset" is different from at7t ksh.
- [see Mail.XXX:XXX]
- [fixed in 5.2.8: fixed error messges in eval.c]
-
-x pdksh 5.2.7, - (reported by Gabor Zahemszky): vi/emacs: when listing
- command/file completions, should go back at most one space. Also, should
- allow completions on zero length names.
- [see Mail.XXX:XXX]
- [fixed in 5.2.8: fixed edit.c(x_locate_word); now allows zero-length
- file completions (but not command)]
-
-* pdksh 5.2.7, - (reported by Gabor Zahemszky): emacs: <esc># doesn't do
- the comment thing.
- [see Mail.XXX:XXX]
- [fixed in 5.2.8: added emacs.c(x_comment) et al.]
-
-x pdksh 5.2.7, - (reported by Gabor Zahemszky): arithmatic expressions
- containing variables not expanded as in at&t ksh. eg, "x=1+2, let y=x"
- fails.
- [see Mail.XXX:XXX]
- [fixed in 5.2.8: added evaling/INEXPREVAL/ET_RECURSIVE code to expr.c]
-
-x pdksh 5.2.7, - (reported by Gabor Zahemszky): unsetting the 0th element
- of an array kills the whole array.
- [see Mail.XXX:XXX]
- [fixed in 5.2.8: var.c(unset) - allow ARRAY to be preserved]
-
-x pdksh 5.2.7, - (reported by Gabor Zahemszky): unsetting a function while
- it is being executed can result in core dump.
- [see Mail.XXX:XXX]
- [fixed in 5.2.8: table.c(texpand) - dont free if FINUSE is set]
-
-* pdksh 5.2.7, - (reported by Gabor Zahemszky): exec 3<&p doesn't close
- shells copy of the coprocess file desc.
- [see Mail.XXX:XXX]
- [fixed in 5.2.8: coprocess stuff made to act like ksh93 co-processes]
-
-x pdksh 5.2.8, - (reported with fix by Lars Hecking): doesn't compile as
- sh - c_ksh.c and jobs.c boom out.
- [see Mail.XXX:XXX]
- [fixed in 5.2.9: added ifdef KSH to appropriate places]
-
-x pdksh 5.2.8, - (reported by Paolo Zeppegno): assignments containing brackets
- are treated as commands.
- [see Mail.XXX:XXX]
- [fixed in 5.2.9: fixed bug in vars.c(skip_wdvarname).]
-
-x pdksh 5.2.5, - (reported by Adrian Marsh): configuration on Linux FT fails.
- Caused by configure script using -g flag - gcc passes -lg to ld, ld fails
- to find -lg (autoconf or Linux FT bug).
- [see Mail.XXX:XXX]
- [fixed in 5.2.9: changed autoconf's -g test to do linking as well.]
-
-x pdksh 5.2.8, Solaris 2.5.1 (reported by Stefan Dalibor): 2 tests
- (xxx-exec-environment-1 and 2) fail because printenv isn't found.
- [see Mail.XXX:XXX]
- [fixed in 5.2.9: changed test to use env instead]
-
-x pdksh 5.2.8, - (reported by Stefan Dalibor): shell assumes 80 columns when
- it starts up if COLUMNS is set correctly in the environ.
- [see Mail.XXX:XXX]
- [fixed in 5.2.9: fixed so window size is checked at startup]
-
-x pdksh 5.2.8, NeXT machines (reported by Kai Wong): clock_t, which lives
- in sys/time.h, isn't found by configure (causes warning messages).
- [fixed in 5.2.9: configure now checks in sys/time.h]
-
-x pdksh 5.2.3, - (reported by Mike Jetzer): in vi, <ESC>= on word with ~
- but no /, beeps (or prints final path comonent?).
- [see Mail.9:66]
- [fixed in 5.2.9: fixed edit.c(add_glob) so no * is appended to ~username]
-
-x pdksh 5.1.3, NeXT machines (reported by Jason Baugher): job control doesn't
- work on NeXT machines (both m68k and x86 based) in rlogin sessions.
- (caused by open("/dev/tty") failing - rlogin on NeXT doesn't set up
- controlling tty properly).
- [see Mail.7:29]
- [fixed in 5.2.9: added hack to main to get a controlling tty]
-
-x pdksh 5.2.8, NeXT 3.2 (reported by Andrew S Townley): the output of the
- siglist.sh script fills the disk. Also, the signal list generated (by the
- fixed script) is mostly empty.
- [see Mail.XXX]
- [fixed in 5.2.9: fixed siglist.sh script to avoid infinite loops. Added
- comment to README warning of problem with NeXT's native cc -E]
-
-x pdksh 5.2.9, - (reported by Loris Talpo): long prompts are messed up in
- vi mode.
- [see Mail.XXX]
- [fixed in 5.2.9: lex.c(pprompt) was broken]
-
-x pdksh 5.2.9, - (reported by Will Renkel): a double backslash followed
- by a newline in an unquoted here document results in one of the backslashes
- and the newline being stripped.
- [see Mail.XXX]
- [fixed in 5.2.10: fixed backslash-newline processing in lex.c]
-
-x pdksh 5.2.9, - (reported by Han Holl): read x?prompt doesn't work
- on non-interactive shells when the input is from a tty.
- [see Mail.XXX]
- [fixed in 5.2.10: changed test in c_read() from FTALKING to isatty]
-
-x pdksh 5.2.10, - (reported by Dale DePriest): expanding aliases causes
- extra input.
- [see Mail.XXX]
- [fixed in 5.2.11: fixed syn.c(c_list).]
-
-x pdksh 5.2.10, - (reported by John Rochester): window size changes don't
- happen on Dec unix (osf) because TIOCGWINSZ is defined in <sys/ioctl.h>
- not in <termios.h>.
- [see Mail.XXX]
- [fixed in 5.2.12: sys/ioctl.h included with termios.h/termio.h if possible]
-
-x pdksh 5.2.11, - (reported by Randy Bouzane): aliases in command substitutions
- result in code dumps.
- [see Mail.XXX]
- [fixed in 5.2.12: lex.c(getsc__): break if eof is read]
-
-x pdksh 5.2.11, - (reported by Will Renkel): aliases containing ;<newline>
- or <newline><newline> aren't fully read/executed.
- [see Mail.XXX]
- [fixed in 5.2.12: syn.c(get_command): call inalias()]
-
-x pdksh 5.2.11, SGI/IRIX 5.2 (reported by bert@xpilot.com): pipelines
- containing built in commands hang forever.
- [see Mail.XXX]
- [fixed in 5.2.12: fixed pgrp sync code in jobs.c]
-
-x pdksh 5.2.11, - (reported by Herbert Thielen via Larry Daffner): shell leaves
- temp files around when executing shell scripts that have functions with
- here documents which end in an exec.
- [see Mail.XXX]
- [fixed in 5.2.12: call main.c(cleanup_proc_env()) from exec.c(execute()).]
-
diff --git a/bin/pdksh/CONTRIBUTORS b/bin/pdksh/CONTRIBUTORS
deleted file mode 100644
index edf32c0db35..00000000000
--- a/bin/pdksh/CONTRIBUTORS
+++ /dev/null
@@ -1,103 +0,0 @@
-$OpenBSD: CONTRIBUTORS,v 1.3 1996/10/01 02:05:25 downsj Exp $
-
-This is a partial history of this shell gleened from old change logs and
-readmes (most of which are still in the misc directory) and the source
-code. Hopefully it is correct and no contributors have been left out
-(file a bug report if you spot a problem :-)).
-
-Release history:
- * Eric Gisin (egisin@math.uwaterloo.ca), created pdksh, using
- Charles Forsyth's public domain V7 shell as a base; also used parts
- of the BRL shell (written by Doug A Gwyn, Doug Kingston, Ron Natalie,
- Arnold Robbins, Lou Salkind, and others?, circa '87; the parts used in
- pdksh included getopts, test builtin, ulimit, tty setting/getting, emacs
- editing, and job control; the test builtin was based on code by Erik
- Baalbergen).
- '87..'89 ?
- Released versions: .. 3.2
- * John R MacMillan (@yonge.csri.toronto.edu:chance!john@sq.sq.com)
- takes over as maintainer
- dates?
- Released versions: 3.3 (?)
- * Simon J. Gerraty (sjg@zen.void.oz.au) takes over as maintainer
- Nov '91..July '94 ?
- Released versions: 4.0 .. 4.9
- * Michael Rendell (michael@cs.mun.ca) takes over as maintainer
- July, 1994
- Released versions: 5.0 .. 5.2
-
-Major contributions:
- * John R MacMillan (@yonge.csri.toronto.edu:chance!john@sq.sq.com), ?:
- cleaned up configuration, many bug fixes (see misc/Changes.jrm).
- * Simon Gerraty, (sjg@zen.void.oz.au), Nov '91..?: much improved emacs mode
- ala at&t ksh, 386bsd port, sigaction routines for non-POSIX systems
- (see misc/ChangeLog.sjg and misc/ReadME.sjg).
- * Peter Collinson (pc@hillside.co.uk), July '92: added select, at&t ksh
- style history file, original csh-style {} globbing, BSD/386 port,
- misc bug fixes.
- * Larry Bouzane (larry@compusult.nf.ca), Mar '89..'93: re-wrote job control,
- added async job notification, added CDPATH and other cd fixes, misc bug
- fixes.
- * John Rochester (jr@cs.mun.ca), '87: wrote vi command line editor; various
- bug fixes/enhancements.
- * Jeff Sparkes (jsparkes@bnr.ca), Mar '89..Mar '90: added arrays,
- merged John Rochester's vi code into pdksh, misc bug fixes.
- * Michael Haardt (u31b3hs@POOL.Informatik.RWTH-Aachen.DE), Sept '94:
- organized man page, filled in many of its copious blank spots; added
- KSH ifdefs.
- * Dale DePriest (daled@cadence.com): ported to OS/2 (initially based on
- port of pdksh4.9 to OS/2 by Kai Rommel (rommel@ars.muc.de)); maintains
- OS/2 port; misc bug fixes.
-
-Other contributors:
- * Piercarlo Grandi (pcg@aber.ac.uk), Dec '93: fixes for linux port
- * Neil Smithline (Neil.Smithline@eng.sun.com), Aug '92: emacs-style
- filename completion.
- * Mike Jetzer [mlj] (jetzer@studsys.mscs.mu.edu), ?;Nov '94: fixes for vi
- mode (see misc/Changes.mlj), added v to vi, fixes for history; fixed
- command redoing in vi; fixes to vi globbing.
- * Robert J Gibson: mailbox checking code that was adapted for pdksh by
- John R. MacMillan.
- * ? (guy@demon.co.uk), ?: promptlen() function.
- * J.T. Conklin (jtc@cygnus.com): POSIXized test builtin; miscellaneous
- fixes/enhancements.
- * Sean Hogan (sean@neweast.ca): fixes for ICS 3.0 Unix, found and helped
- fix numerous problems.
- * Gordan Larson (hoh@approve.se): fix to compile sans VI, ksh.1 typo.
- * Thomas Gellekum (thomas@ghpc8.ihf.rwth-aachen.de): fixes for Makefile
- typos, fixed CLK_TCK for FreeBSD, man page fixes.
- * Ed Ferguson (Ed.Ferguson@dseg.ti.com): fix to compile sans VI.
- * Brian Campbell (brianc@qnx.com): fixes to compile under QNX and
- to compile with dmake.
- * (guy@netapp.com), Oct '94: patch to use gmacs flag.
- * Andrew Moore (alm@netcom.com): reported many bugs, fixes.
- * William Bader (wbader@CSEE.Lehigh.Edu): fix to compile on SCO Unix
- (strut winsize).
- * Mike Long (mike.long@analog.com): makefile fix - use $manext, not 1.
- * Art Mills (aem@hpbs9162.bio.hp.com): bug fix for vi file completion in
- command mode.
- * Tory Bollinger (tboll@authstin.ibm.com): allow ~ in vi mode to take
- a count.
- * Frank Edwards (<crash@azhrei.EEC.COM>): added macros to vi (@char).
- * Fritz Heinrichmeyer (<Fritz.Heinrichmeyer@FernUni-Hagen.de>): fixes
- to allow compile under Linux 1.4.3.
- * Gabor Zahemszky (<zgabor@CoDe.hu>): SVR3_PGRP vs SYSV_PGRP, many
- bug reports and man page fixes.
- * Dave Kinchlea (<kinch@julian.uwo.ca>): DEFAULT_ENV patches.
- * Paul Borman (<prb@bsdi.com>): j_exit: send HUP, then CONT; HUP fg process.
- * DaviD W. Sanderson (<dws@ssec.wisc.edu>): patches to allow { .. } instead
- of in .. esac in case statements.
- * ? (<ra@rhi.hi.is>): partial patches to handle SIGWINCH for command line
- editing.
- * Jason Tyler (<jason@nc.bhpese.oz.au>): fixes for bugs in fc.
- * Stefan Dalibor (<Stefan.Dalibor@informatik.uni-erlangen.de>): fix for
- COLUMNS never being set in x_init().
- * Arnon Kanfi (<arnon@gilly.datatools.com>): fix for prompt.
- * Marc Olzheim (<marcolz@stack.urc.tue.nl>): patches to ifdef KSH the
- mail check code and aliases.
- * Lars Hecking (<lhecking@nmrc.ucc.ie>): fixes so shell compiles as sh
- again.
- * Bill Kish (<kish@browncow.com>): added prompt delimiter hack for
- hidden characters (eg, escape codes).
- * Andrew S. Townley (<atownley@informix.com>): fixes for NeXT machines:
- get a controlling if one needed, use correct profile.
diff --git a/bin/pdksh/ChangeLog b/bin/pdksh/ChangeLog
deleted file mode 100644
index b515993f3aa..00000000000
--- a/bin/pdksh/ChangeLog
+++ /dev/null
@@ -1,1071 +0,0 @@
-$OpenBSD: ChangeLog,v 1.5 1996/11/21 07:59:25 downsj Exp $
-
-Tue Oct 29 11:34:58 NST 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * made pdksh-5.2.12 distribution
-
-Fri Oct 25 11:59:48 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * vi.c(vi_cmd): case Cntl('i'): dont fall through, call complete_word().
-
-Tue Oct 22 17:38:21 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * table.h(USERATTRIB): new define.
- * c_ksh.c(c_typeset): report unset params only if it has some
- interesting attributes.
-
-Tue Oct 22 15:54:39 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * jobs.c(exchild): changed NEED_PGRP_SYNC code so j_sync_pipe[1] isn't
- left open in 2nd+ children.
-
-Tue Oct 22 12:59:49 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * main.c(main): memset() env to 0.
-
-Mon Oct 21 12:53:44 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * main.c(cleanup_proc_env): new function.
- * exec.c(execute): call cleanup_proc_env() before calling ksh_execve().
-
-Fri Oct 11 22:53:57 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * vi.c(display): use ch not e->buf[cur] when printing character.
-
-Fri Oct 11 13:26:11 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * aclocal.m4(KSH_TIMES_CHECK,KSH_DUP2_CLEXEC_CHECK,KSH_OPENDIR_CHECK):
- changed sense of test so "yes" result is printed if you have a good
- system.
- * aclocal.m4(KSH_C_FUNC_ATTR): changed return type of test_cnst to int.
-
-Fri Oct 11 13:05:40 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * syn.c(get_command): added inalias() call when setting cf = CONTIN.
-
-Thu Oct 10 16:22:03 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * lex.c(getsc__): case SALIAS: if we read eof, break, don't continue.
-
-Tue Oct 8 13:14:00 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * aclocal.m4(KSH_TERM): added SYS_IOCTL_WITH_TERMIOS,
- SYS_IOCTL_WITH_TERMIO tests.
- * tty.h: include <sys/ioctl.h> with <termios.h>/<termio.h>
- if possible.
-
-Tue Oct 8 11:42:36 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * made pdksh-5.2.11 distribution
-
-Tue Oct 8 11:02:54 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * syn.c(inalias): new function.
- * syn.c(c_list): call inalias() instead of testing source->type.
-
-Mon Oct 7 17:00:40 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * made pdksh-5.2.10 distribution
-
-Mon Oct 7 16:23:53 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * c_sh.c(c_read): when printing prompt, use isatty, not FTALKING.
-
-Wed Oct 2 12:00:51 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * lex.c(yylex): redirection stuff: save result of getsc() == '-'
- and use it for ungetsc().
-
- * lex.h(struct source): moved ugbuf out of union so it can be used
- with alias stuff.
- * lex.c(getsc__) case SALIAS: instead of appending a space, get the
- next character and stuff it in ugbuf.
-
- * lex.c(getsc_,getsc__): getsc_() renamed to getsc__().
- * lex.c(getsc_,getsc): getsc() macro renamed to getsc_().
- * lex.c(backslash_skip,ignore_backslash_newline): new variables.
- * lex.c(getsc): new macro that checks backslash_skip.
- * lex.c(getsc_bn_,getsc_bn): getsc_bn() macro deleted (all calls
- replaced with getsc()); getsc_bn_ renamed to getsc_bn.
- * lex.c(ungetsc_,ungetsc): ungetsc() macro deleted; renamed ungetsc_()
- to ungetsc().
- * lex.c(yylex,ungetsc,getsc_bn): set and use backslash_skip,
- ignore_backslash_newline.
- * lex.c(yylex): removed special cases for backslash-newline sequence,
- explicitly ignore backslash followed by eof.
-
-Mon Sep 30 17:14:41 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * made pdksh-5.2.9 distribution
-
-Mon Sep 30 12:52:21 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * lex.c(pprompt): fixed usage of ntruncate.
-
-Thu Sep 19 17:43:33 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * sh.h(KSH_SYSTEM_PROFILE): new define.
- * main.c(main): use KSH_SYSTEM_PROFILE.
-
- * aclocal.m4(KSH_OS_TYPE): added case for NEXT.
-
-Thu Sep 19 15:39:54 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * tty.c(tty_init): added hack for NeXT's rlogin's missing controlling
- tty.
-
-Mon Sep 16 11:18:10 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * edit.c(add_glob): don't append a * to a ~username.
-
- * edit.c(x_init): set got_sigwinch before calling check_sigwinch().
-
-Wed Sep 11 14:38:38 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * c_ksh.c(c_let): ifdef'd KSH.
- * lex.h(SDPAREN),lex.c: ifdef'd KSH all uses of SDPAREN.
- * lex.h(MDPAREN),syn.c: ifdef'd KSH all uses of MDPAREN.
-
-Mon Sep 9 16:18:03 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * aclocal.m4(AC_PROG_CC): replaced autoconf's version with
- modified version.
-
- * configure.in(clock_t): check in sys/time.h as well.
- * ksh_times.h: include ksh_time.h.
- * ksh_time.h,ksh_times.h: added ifndef KSH_TIME_H/KSH_TIMES_H.
-
-Fri Sep 6 13:20:24 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * edit.c(promptlen): X\r hack for delimiting hidden characters
- in prompt.
- (Based on fix from Bill Kish)
-
-Tue Sep 3 11:03:26 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * Makefile.in: removed options.h from HDRS (also removed file).
-
-Thu Aug 29 10:04:01 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * aclocal.m4(KSH_MEMMOVE): added return 0 to end of main().
-
-Fri Aug 23 14:23:50 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * aclocal.m4,ksh_stat.h: changed S_IFFIFO to S_IFIFO.
-
-Fri Aug 23 09:58:09 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * var.c(skip_wdvarname): don't check for array if first char
- isn't [.
-
-Thu Aug 22 12:51:25 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * jobs.c: added ifdef KSH around Coproc_id/j->coproc_id usagae.
- * c_ksh.c(c_read): added ifdef KSH around opipe.
-
-Tue Aug 20 09:41:32 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * configure.in: fixed quoting of sed LDSTATIC expression.
-
-Mon Aug 19 14:26:08 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * made pdksh-5.2.8 distribution
-
-Mon Aug 19 11:38:16 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * table.c(texpand): don't free entry if FINUSE is set.
-
- * var.c(unset): preserve ARRAY and DEFINED if unsetting foo[0].
-
-Thu Aug 15 15:08:52 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * jobs.c(sm_sigchld,sm_default): moved to sh.h.
- * sh.h(Coproc_id, struct coproc): new typedef; added njobs and
- id fields to struct coproc.
- * exec.c(execute): case TCOPROC: re-did coprocess stuff to use
- njobs/coprocess id.
- * jobs.c(struct Job): added coproc_id field.
- * jobs.c(exchild): initialize coproc_id to 0; set job coproc_id
- and increment coproc.njobs in parent.
- * jobs.c(checkjob): check coproc_id and close co-process input/output
- if needed.
-
- * exec.c(iosetup): only play with coprocess fds if this is an
- empty exec.
- * c_sh.c(c_read): commented out coproc_readw_close() call and eof call.
- * c_ksh.c(c_print): commented out closing coprocess fd on EPIPE.
-
- * jobs.c(exchild): in parent, last part of job: use orig_flags (not
- flags) when checking XCOPROC.
-
-Thu Aug 15 15:00:42 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * io.c(get_coproc_fd,cleanup_coproc): renamed to coproc_getfd() and
- coproc_cleanup(), respecitively; changed all calls.
-
-Tue Aug 13 16:56:59 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * expr.c(O_COMMA,P_COMMA): new enums.
- * expr.c(evalexpr): added case for O_COMMA.
-
-Tue Aug 13 15:18:28 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * expr.c(do_ppmm): new function to handle ++/--.
- * expr.c(evalexpr): call do_ppmm() in P_PRIMARY code.
- * expr.c(LAST_BINOP): deleted.
- * expr.c(IS_BINOP): new define.
- * expr.c(evalexpr): use IS_BINOP.
- * expr.c(O_PLUSPLUS,O_MINUSMUNS,opinfo[]): new enums; updated opinfo
- * expr.c(ET_LVALUE,ET_RDONLY): new enums.
-
- * expr.c(token): var code: don't increment cp in iter part of for loop,
- do it in body; don't correct for off by 1 in array or !noasign code.
- * table.h(EXPRLVALUE): new define.
- * expr.c(token): var code: set EXPRLVALUE flag if noassign.
- * expr.c(intvar): copy temp var if EXPRLVALUE set.
- * expr.c(assign_check): new function.
- * expr.c(evalexpr): if assign-op, call assign_check().
-
-Tue Aug 13 11:02:32 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * vi.c(do_comment),edit.c(x_do_comment): made do_comment generic,
- renamed and moved to edit.c; changed all calls.
- * emacs.c(x_ftab[]): added x_comment.
- * emacs.c(x_defbindings[]): added XFUNC_comment as <esc>#.
- * emacs.c(x_comment): new function.
-
-Mon Aug 12 16:13:36 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * expr.c(ET_BADVAR): deleted.
- * expr.c(ET_RECURSIVE, struct expr.evaling),table.h(EXPRNEVAL): added.
- * expr.c(v_evaluate): if curstate.evaling set, clear EXPRINEVAL.
- * expr.c(evalerr): added ET_RECURSIVE case, removed ET_BADVAR case.
- * expr.c(intvar): do recursion check, call v_evaluate() on value.
-
-Mon Aug 12 14:25:23 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * io.c(coproc_read_close): call coproc_readw_close() instead of
- duplicating code.
-
-Mon Aug 12 11:21:39 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * edit.c(x_locate_word): changed to allow at most 1 leading blank
- before the word.
- * edit.c(x_file_glob,x_command_glob,add_glob): allow zero length word.
- * edit.c(x_cf_glob): allow zero length globs on when doing file
- completion.
-
- * edit.c(x_complete_word): #if 0 - it isn't used...
- * edit.c(x_file_glob,x_command_glob,x_locate_word): made static.
-
- * eval.c(varsub): changed FNOUNSET error from "unset variable"
- to "parameter no set", ala at&t ksh.
-
- * c_ksh.c(c_typeset): print variables that aren't set (just
- leave out the =...).
-
-Mon Aug 12 11:03:22 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * exec.c(findfunc): removed redundent DEFINED check after tsearch().
-
-Fri Aug 9 22:16:21 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * jobs.c(j_change): when turning off FMONITOR and not FTALKING,
- changed SS_RESTORE_CURR to SS_RESTORE_ORIG.
-
- * edit.c(x_sigwinch): new function.
- * edit.c(x_init): set up signal handler for SIGWINCH; moved
- code to get window size into x_sigwinch(); call x_sigwinch().
- * emacs.c(xx_cols): new variable.
- * emacs.c(x_init): set xx_cols_to x_cols; change all uses of x_cols
- to xx_cols.
- * vi.c(display): when displaying morec, changed x_cols-2 to
- pwidth+winwidth+1.
-
-Fri Aug 9 12:49:00 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * table.h(FKSH): new define.
- * tree.h(struct op): put evalflags into new union u, added ksh_func
- to union; changed all uses of evalflags.
- * syn.c(function_body): set u.ksh_func.
- * exec.c(execute): changed define() arg to t (was t->left).
- * exec.c(define): copy t->left (was t); set FKSH in flag if is
- a ksh function.
- * exec.c(comexec): don't keep assignments for x() style functions.
- * exec.c(comexec: case CFUNC: set kshname ($0) for ksh style functions
- only (was FPOSIX).
-
- * exec.c(execute): case TAND/TOR: pass XERROK on when executing right
- hand side.
-
- * jobs.c(exchild): deleted redundant code to set j->flags
- (near new_job() call).
-
- * sh.h(ksh_tmout),main.c(alarm_init),trap.c(alarm_init,alarm_catcher):
- ifdef'd KSH.
-
- * sh.h(SS_SHTRAP,Trap.shtrap): added.
- * trap.c(trapsig): if shtrap is non-zero, call it.
- * trap.c(setsig): set shtrap if SS_SHTRAP set.
- * jobs.c(j_init),trap.c(alarm_init): pass SS_SHTRAP.
- * jobs.c(j_sigchld),trap.c(alarm_catcher): don't call trapsig().
- * trap.c(Sigact_alarm): removed.
-
-Thu Aug 8 15:57:14 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * exec.c(comexec): case CEXEC: print cannot execute error only
- if / in pathname; also, set exit code to 126.
-
- * exec.c(do_selectargs): added print_menu arg; only print
- menu if this is set, or if REPLY is null; removed "while isspace"
- loop.
- * exec.c(execute): case TSELECT: call do_selectargs with print_menu
- of TRUE on first call only.
-
- * exec.c(define): added was_set variable and logic.
- * c_sh.c(c_unset): return 1 if variable/function to be unset wasn't
- set to begin with.
-
-Wed Jul 31 10:33:00 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * sh.h(Tflag): new type.
- * sh.h(builtin_flag): changed type to Tflag.
- * table.h(struct tbl): changed type of flag field to Tflag.
- * c_ksh.c(typeset): changed type of flag, fset, fclr to Tflag.
- * c_ksh.c(c_alias): changed type of xflag to Tflag.
- * exec.c(comexec): changed type of old_inuse to Tflag.
- * exec.c(builtin): changed type of flag to Tflag.
- * var.c(typeset): changed set, clr args to Tflag; convert second
- arg of call to local() to boolean.
-
-Wed Jul 31 10:26:25 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * sh.h(C_QUOTE): new define.
- * sh.h(ctypes[]),misc.c(ctypes[]): changed from char to short.
- * misc.c(initctypes): set C_QUOTE bits in ctypes[].
- * misc.c(print_value_quoted): use C_QUOTE.
-
-Mon Jul 29 11:38:36 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * lex.c(set_prompt): don't print warning message if setjmp returns
- non-zero.
-
-Fri Jul 26 10:16:27 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * lex.c(set_prompt): don't do ! and parameter expansion if !KSH.
-
- * table.h(V_MAIL,V_MAILPATH,V_MAILCHECK): ifdef KSH.
- * var.c(initvar,setspec,unsetspec): ifdef KSH use of MAIL stuff.
- * mail.c: ifdef KSH whole file.
- * main.c(shell): ifdef KSH call to mcheck().
- * main.c(initcoms[]): ifdef KSH the MAILCHECK=600.
- (based on patches from Marc Olzheim).
-
- * exec.c(PS4_SUBSTITUTE): new macro.
- * exec.c(execute, comexec, iosetup): use PS4_SUBSTITUTE.
-
-Thu Jul 25 17:19:17 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * sh.h(F_VIESCCOMPLETE): new define.
- * misc.c(options[]): added vi-esccomplete.
- * vi.c(classify[]): make ^[ a repeatable command.
- * vi.c(vi_cmd): check F_VIESCCOMPLETE for ^[.
-
-Mon Jul 22 16:54:38 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * c_ksh.c(c_getopts): return if variable is readonly; don't change
- OPTIND if option is bad (fragile).
- * c_sh.c(c_brkcont): use ksh_getopt(); changed error message if
- n <= 0.
- * c_sh.c(c_dot,c_eval,c_exitreturn): use ksh_getopt().
- * misc.c(ksh_getopt): print `unknown option' instead of `bad option'.
-
-Mon Jul 22 16:08:40 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * edit.c(x_init): do NOT export COLUMNS/LINES - causes more problems
- than it fixes.
-
-Mon Jul 22 15:49:35 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * syn.c(get_command): fixed test for '< foo (command)' so it
- works.
-
-Fri Jun 21 09:57:47 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * aclocal.m4(KSH_OPENDIR_CHECK): include dirent.h if HAVE_DIRENT_H
- defined (was DIRENT || _POSIX_VERSION).
- * aclocal.m4(KSH_UNISTD_H): don't test HAVE_DIRENT_H when including
- dirent.h.
-
-Wed Jun 12 11:02:32 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * c_test.c(b_ops[]): added "==" entry (ksh93ism).
-
-Mon Jun 10 14:00:21 1996 Michael Rendell (michael@lyman.cs.mun.ca)
-
- * ksh_stat.h: undef S_ISSOCK if STAT_MACROS_BROKEN defined.
- * aclocal.m4(AC_HEADER_STAT): redefine autoconf's version to handle
- FreeBSD's S_ISSOCK.
-
-Tue Jun 4 08:41:19 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * made pdksh-5.2.7 distribution
-
- * vi.c(CMDLEN): changed from 16 back to 1024.
-
-Sun Jun 2 11:54:46 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * made pdksh-5.2.6 distribution
-
-Sun Jun 2 11:46:56 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * exec.c(search_access): changed ordering of xsuffixes[], rsuffixes[];
- removed code that used xsuffixes[] when suffix is present.
- * lex.c(getsc_line): set O_TEXT/O_BINARY if os/2.
- * main.c(remove_temps): added os2 ifdefs.
- [Changes from Dale DePriest.]
-
-Tue May 21 14:18:22 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * vi.c(vi_cmd): case '#': call do_comment() to do work.
- * vi.c(do_comment): new function.
- * vi.c(putbuf,grabhist,grabsearch): fixed pesimestic off-by-1 error
- (cbufsize - 1 -> cbufsize).
- * vi.c(vi_hook): case VCMD: case -1: added refresh(0).
- * vi.c(vi_cmd): case 'P': don't move cursor back if nothing added.
-
-Tue May 21 12:03:34 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * emacs.c(do_complete): don't add space if single match and
- it doesn't end with a /.
-
-Tue May 21 11:51:36 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * edit.c(x_init): use typeset to set EXPORT attribute for
- COLUMNS/LINES.
-
-Tue May 21 11:40:12 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * misc.c(parseargs): option setting: ignore context if option
- isn't being changed.
- * misc.c(printoptions): for non-verbose mode: print a set command
- (eg, set -o vi -o ...) instead of just the option names.
-
-Tue May 21 11:14:27 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * c_sh.c(c_brkcont): if n is too big, use last enclosing loop.
-
-Fri May 10 09:27:47 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * sh.h(Getopt): changed field p from int to unsigned.
-
-Tue May 7 12:10:47 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * made pdksh-5.2.5 distribution
-
-Tue May 7 11:45:37 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * syn.c(compile): set multiline if source is SSTRING.
- * syn.c(yyparse): don't peek before calling c_list() - build
- TEOF if c_list() fails and c is 0.
- * syn.c(c_list): remove SSTRING test.
- * syn.c(get_command): if EOF is reached, free iops,args,vars.
- * syn.c(syntaxerr): set multiline.on to false when it is used;
- don't use multiline.on if start token is 0.
-
-Tue May 7 10:11:41 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * history.c(c_fc,hist_execute): moved calls to histbackup() from
- c_fc() to hist_execute().
- * history.c(hist_get): number: took out +1 correction as histbackup
- hasn't been done yet; string: added -1 correction to ensure
- current fc command isn't searched.
- * history.c(hist_get_newest,hist_get_oldest): don't find the
- current (fc) command; removed print_err argument (was always
- true).
- * history.c(hist_get,hist_get_newest): added allow_cur argument;
- changed all calls.
-
-Mon May 6 09:55:29 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * emacs.c(x_nextcmdp): renamed to x_nextcmd, changed from
- char ** to int.
- * emacs.c(x_nl_next_com): save absolute command number, not
- relative position in history array (which changes).
- * emacs.c(x_emacs): convert x_nextcmd back to relative position.
- * emacs.c(x_init_emacs): initialize x_nextcmd to -1.
-
-Sun May 5 13:10:48 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * expr.c(evalexpr): when assigning a non-integer, call setint()
- (not setstr(..., strval(...))).
-
-Sun May 5 12:16:11 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * mail.c(maddmsg): changed name to mprintit(); now prints message
- directly instead of saving in a linked list; changed all calls.
- * mail.c(mprint): deleted; deleted all calls.
- * mail.c(mmsgs,struct mailmsg): deleted.
-
-Sun May 5 11:52:05 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * lex.h(SF_TTY): new flag.
- * lex.h(STTY): deleted.
- * main.c(main): if tty, use SSTDIN, set SF_TTY.
- * main.c(shell): check SF_TTY instead of STTY.
- * lex.c(getsc_): call getsc_line for SSTDIN/SFILE.
- * lex.c(getsc_line): new function (merged old STTY/SSTDIN/SFILE code).
-
-Fri May 3 11:24:17 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * main.c(shell): changed exit_atend to toplevel. Changed interactive
- to be falking&toplevel (was talking&s->type==STTY).
-
-Fri May 3 10:59:22 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * var.c(getint): only allow one base (ie, disallow 2#4#5).
-
-Thu May 2 21:31:23 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * var.c(array_index_calc): new function
- * var.c(global): call array_index_calc(); moved $2 code into
- if (!letter(c))...
- * var.c(local): call array_index_calc(); added copy argument & code;
- changed all calls.
- * table.h(LOCAL_COPY): new define.
- * exec.c(comexec): maybe pass LOCAL_COPY to typeset().
-
-Thu May 2 16:34:29 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * emacs.c: command completion changes.
- * emacs.c(Comp_type,CT_LIST,CT_COMPLETE,CT_COMPLIST): new type.
- * emacs.c(x_ins): return type changed to int; return -1 if
- string can't be inserted.
- * emacs.c(x_do_ins): new function.
- * emacs.c(add_stash,list_stash,compl_dec,compl_file,compl_command,
- str_match): deleted; changed callers to use do_complete().
- * emacs.c(do_complete,x_expand): new functions.
- * emacs.c(x_ftab[],x_defbindings[]): added entry for file-expand;
- bound to <ESC>*.
-
-Thu May 2 15:31:32 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * lex.c(set_prompt): pass strlen() + 1 to shf_sopen.
- (fix from Arnon Kanfi).
-
-Wed Apr 24 11:50:52 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * history.c(c_fc): -e -: don't increment wp past null; allow
- pat=replace arg with "-1" type argument.
- (based on fix from Jason Tyler).
-
-Mon Apr 15 11:58:34 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * table.c(tenter),alloc.c(alloc): changed use of offsetof() so field
- parameter is a constant expression.
- * sh.h: took out undef of offsetof on CRAYs.
-
-Fri Apr 12 16:01:40 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * jobs.c(JF_USETTYMODE): renamed JR_ORIGFG to JF_USETTYMODE.
- * jobs.c(j_waitj): clear JF_USETTYMODE if fg job is stopped.
-
-Sun Apr 7 12:35:30 NDT 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * c_ksh(c_print): echo: don't treat a lone minus as an option.
-
-Sat Apr 6 00:09:37 NST 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * c_ulimit.c(c_ulimit.c): always pass 2 args to ulimit().
- * ksh_sigsetjmp(): changed all uses to be simple expressions - seems
- to be required by the cray C compiler.
- * sh.h(offsetof): undef if on a cray.
- (based on fixes from Dave Kinchlea)
-
-Sat Mar 23 13:58:12 NST 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * siglist.in: added WAITING,LWP,FREEZE,THAW,CANCEL
-
-Thu Mar 7 23:26:37 NST 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * edit.c(x_init): set LINES if possible.
-
-Thu Mar 7 23:01:55 NST 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * main.c(main): call x_init() after j_init()
- (based on fix from Stefan Dalibor).
-
-Thu Mar 7 16:13:10 NST 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * aclocal.m4(KSH_OS_TYPE): check for TitanOS (use cc -43).
- * aclocal.m4(KSH_SIGNAL_TYPE): for bsd41 signals, check if signal
- interrupt read().
-
-Thu Mar 7 13:59:29 NST 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * sh.h(strstr),missing.c(strstr): changed args to const.
-
-Wed Mar 6 17:21:36 NST 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * io.c(errorf,bi_errorf): changed null pointer string check to
- empty string; changed all calls (due to new error gcc warnings).
-
-Wed Mar 6 17:15:58 NST 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * exec.c(search_access): files aren't executable if they don't
- have any execute bits.
- * ksh_stat.h: added S_IXUSR,S_IXGRP,S_IXOTH.
- * exec.c(search_access,search_access1): OS2: changed the meaning
- of these two functions (search_access1 now called from search_access).
-
-Wed Mar 6 16:23:23 NST 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * tree.c(ptree): add case for TSELECT.
-
-Wed Mar 6 12:40:34 NST 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * vi.c(Z_,is_zeroarg): new defines.
- * vi.c(classify): use Z_ for G, g, _, |, v, ^I, ^F.
- * vi.c(vi_cmd): use is_zerocount().
- * vi.c(complete_word): if command prefixed by a count, complete
- to count'th expansion (as reported by print_expansions()).
-
-Tue Mar 5 14:43:48 NST 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * eval.c(GF_NONE,GF_EXCHECK,GF_GLOBBED,GF_MARKDIR): new defines.
- * eval.c(glob_str): added markdirs argument; changed all calls;
- made function non-static.
- * eval.c(glob): added markdirs argument; changed all calls.
- * tree.h(DOMARKDIRS): new define.
- * eval.c(expand): set DOMARKDIRS if FMARKDIRS.
- * edit.c(x_complete_word,x_print_expansions,x_file_glob,x_command_glob,
- x_locate_word,x_cf_glob,x_add_glob,x_longest_prefix,x_free_words):
- new functions.
- * proto,edit.h: moved functions defined in edit.c to edit.h.
- * vi.c(struct edstate): moved to top of file.
- * vi.c(print_expansions): added struct edstate argument; changed all
- calls.
- * vi.c(struct glob,Glob,globstr,glob_word,): deleted
- * vi.c(vi_pprompt): new function; changed all calls of pprompt() in
- vi.c to use vi_pprompt().
- * vi.c(x_vi): moved to top of file.
- * vi.c(expand_word,complete_word): free buf if it is not null.
- * vi.c(expand_word,complete_word,print_expansions): changed
- to use new edit.c functions.
-
-Tue Feb 20 11:02:05 NST 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * table.c(twalk,tnext,struct tstate),table.h(struct tstate): moved
- struct tstate from table.c to table.h; changed twalk,tnext to take
- struct tstate* argument; changed all calls; deleted static tstate
- variable.
-
-Sat Feb 17 12:28:11 NST 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * vi.c(vi_hook): case VSEARCH: if new pattern is empty, repeat last
- search.
-
-Sat Feb 10 15:59:28 NST 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * table.h(struct arg_info): new struct.
- * table.h(struct block): changed argv, argc fields to argi.
-
-Sat Feb 10 15:12:47 NST 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- ANSI C name space requirements:
-
- * vi.c(isbad,iscmd,islong,ismove,issrch,isundoable,iswordch): changed
- to is_bad,is_cmd,is_long,is_move,is_srch,is_undoable,is_wordch.
- * emacs.c(iscfs,ismfs): changed to is_cfs, is_mfs.
- * emacs.c(strmatch): changed to str_match.
- * sh.h(strchr_dirsep,strrchr_dirsep): changed to ksh_strchr_dirsep,
- ksh_strtchr_dirsep; changed all calls.
- * missing.c(strichars[]): changed to ichars[].
- * var.c(strint,strval): changed to setint_v, str_val.
- * missing.c(strsave,strnsave): changed to str_save,str_nsave.
-
-Fri Feb 9 11:30:15 NST 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * main.c(main): remove envp parameter; declare and use environ.
-
- * c_ksh.c(c_print): octal digit escape sequences must start with \0.
-
-Sat Feb 3 15:35:41 NST 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * vi.c(vi_cmd,classify[]): made ^I a command.
-
-Fri Feb 2 10:40:32 NST 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * lex.h(struct source): added u.freeme field.
- * lex.c(getsc_): case SREREAD: free u.freeme iff start isn't u.ugbuf.
-
-Thu Feb 1 15:27:06 NST 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * c_test.h(Test_env): added end union.
- * c_test.c(c_test): keep track of end postition using end.wp;
- don't write on wp.
-
- * emacs.c(x_mapin): changed to dup string, then munge; return duped;
- changed all calls.
-
- * eval.c(homedir): deleted getpwnam() declaration - can't believe
- its needed anywhere (we shall see, though).
-
- * sh.h(handler_t): use ARGS for prototype; use h
- * sh.h(struct trap),trap.c(setsig,settrap),sigact.c,sigact.h:
- use handler_t.
- * history.c,c_sh.c,c_ksh.c: removed register declaration from
- c_*() functions.
- * exec.c(builtin),proto.h(builtin): use prototype for func.
- * misc.c(qsortp,qsort1),proto.h(qsortp): use prototype for f.
-
- * c_ksh.c(ksh_getopt): made options arg const.
- * tree.c(fptreef,snptreef,vfptreef): made fmt arg const.
- * jobs.c(waitfor,j_kill,j_resume,j_lookup,j_jobs): made cp arg const.
- * shf.c(shf_snprintf,shf_smprintf,shf_vfprintf): made fmt arg const.
- * c_test.h(Test_env.error),c_test.c(ptest_error): made msg arg const.
- * c_test.c(test_stat,test_eaccess): made path arg const.
- * c_test.c(ptest_getopnd,dbteste_getopnd): made return value const.
- * c_test.c(ptest_eval,test_eval,dbteste_eval,dbtestp_eval,test_primary):
- made opnd1,opnd2 arg const.
- * c_test.c(test_isop): made s arg const.
-
- * misc.c(bi_getn,getn): made as arg const.
- * misc.c(getn): made as arg const.
- * misc.c(gmatch): made s/p arg const.
- * misc.c(has_globbing): made xp/xpe arg const.
- * misc.c(do_gmatch): made s/p/se/pe arg const.
- * misc.c(cclass): made p arg const.
-
-Thu Feb 1 14:54:32 NST 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * edit.h, sh.h, tty.h: changed _I_ to I__.
- * edit.h, edit.c: changed _D_ to D__.
-
- * jobs.c,shf.c,tty.c: include ksh_stat.h (POSIX: needed for open).
-
- * sigact.c: use ARGS instead of __P; comment out __P defines.
-
- * shf.c: include math.h if FP.
- * shf.c(my_ceil): remove modf() declaration.
- * shf.c(shf_fvprintf): comment out frexp() declaration; changed
- exp to expo.
-
- * jobs.c(struct job, j_utime, j_stime): changed utime/stime to
- usrtime/systime; change j_utime/j_stime to j_usrtime/j_systime.
-
-Wed Jan 31 16:13:44 NST 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * edit.c(x_getc): cast return value to int to avoid warnings on
- strange compilers.
- * exec.c(funcfunc): changed second arg to unsigned int (was int).
- * syn.c(elsepart): move return NULL to end of function (avoids
- warning from some compilers).
- * vi.c(classify[]): changed type to unsigned char.
- * shf.c(shf_smprintf): delete unused variable n.
- * aclocal.m4(KSH_TIMES_CHECK): define INT32 in test code.
- * aclocal.m4(KSH_SIGNAL_CHECK): typeo: had bsd42 instead of bsd41.
- * sh.h(MAGIC): changed to 7 to increase portability.
- * jobs.c(tcsetpgrp,tcgetpgrp): define if TTY_PGRP (was TIOCSPGRP).
-
-Tue Jan 23 11:40:25 NST 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * sh.h(ksh_jmp_buf): new define.
-
-Thu Jan 18 15:03:19 NST 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * history.c(hist_replace): fixed substitution code (again).
-
-Wed Jan 17 20:10:02 NST 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * made pdksh-5.2.4 distribution
-
- * main.c(initcoms): changed hash alias to "hash=alias -t".
-
- * exec.c(do_selectargs): deleted c_read() declaration.
-
- * c_ksh(c_alias): call ksh_getopt_reset() before calling c_unalias().
-
-Wed Jan 17 19:47:55 NST 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * history.c(histbackup): changed "histptr > history"
- to "histptr >= history".
-
- * history.c(hist_replace): removed un-needed "last" - use "s" instead.
- (based on fix from Jason Tyler).
-
-Thu Jan 11 15:59:46 NST 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * c_ksh.c(c_whence,c_command),main.c(initcoms[]): removed ifdef KSH
- (type is a builtin in sys-5 sh).
-
-Wed Jan 10 11:49:59 NST 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * Makefile.in: added NEWS.os2 to OS2FILES.
-
- * version.c: include "sh.h" (needed for const define).
-
- * exec.c(pr_menu): made non-static.
- * vi.c(print_expansions): gather expansions into an arrat
- and use pr_menu().
- (fixes from Mike Jetzer).
-
- * vi.c(redraw_line): added newline option; changed all calls.
-
-Wed Jan 10 10:21:06 NST 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * vi.c(classify): made 'U' a C_.
- * vi.c(ohnum): new variable.
- * vi.c(vi_reset): set ohnum to hlast.
- * vi.c(grabhist): set ohnum.
- * vi.c(vi_cmd): case n,N,/,? set ohnum; added case 'U'.
- * vi.c(edit_reset): clear holdlen.
- (based on fix from Dale DePriest).
-
-Tue Jan 9 11:23:36 NST 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * emacs.c(iscfs): make ', " seperators.
- (fix from Dale DePriest).
-
- * conf-end.h: deleted stuff to undef HISTORY, VI, EMACS, etc if
- KSH wasn't defined (now done in configure).
-
- * sh.h(GI_NONAME): changed to GF_NONAME; changed all uses.
-
- * configure.in: added AC_ARG_PROGRAM.
- * Makefile.in: replaced binprefix and manprefix with
- program_transform stuff.
-
-Mon Jan 8 11:42:46 NST 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * sh.h(struct temp): added shf field.
- * io.c(maketemp): changed to use O_EXCL; keep trying if open
- fails (due to O_EXCL); fill in shf field; changed all calls.
-
- * main.c(include): added intr_ok flag; changed all calls.
-
- * main.c(main): if compiled as sh and posix option not set, do not
- include $ENV.
-
- * trap.c: define FROM_TRAP_C before including sh.h.
- * sh.h: don't declare sigtraps if FROM_TRAP_C declared.
-
- * c_ksh.c(c_cd): fixed error message.
- * vi.c(glob_word): don't add * if word contains a $.
- (Based on fixes from Mike Jetzer).
-
- * eval.c(tilde): if HOME,PWD,OLDPWD aren't set, don't expand
- ~,~+/~-.
-
-Fri Jan 5 12:15:58 NST 1996 Michael Rendell (michael@garfield.cs.mun.ca)
-
- * c_ksh.c(c_typeset): seperate loop for printing functions
- (do not traverse array link).
- * c_ksh.c(c_typeset): list functions: do not ignore unset functions.
- * exec.c(findfunc): set val.t to 0 when creating new entry.
- * exec.c(define): if FINUSE, use tail recursion.
-
-Thu Jan 4 11:10:22 NST 1996 Michael Rendell (michael@panda.cs.mun.ca)
-
- * vi.c(globstr): deleted ifdef'd out code.
-
-Sun Dec 10 11:07:52 NST 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * lex.c(yylex): added case for STBRACE; wrap word part of
- trim substitution in @(..).
- * eval.c(trimsub): deleted code to wrap pattern in @(..); changed
- '%' code to use strnsave().
-
-Fri Dec 8 22:55:56 NST 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * eval.c(trimsub): if trim pattern contains a |, wrap pattern
- in @(...).
- * lex.c(yylex): make | special when incounted in a ${...}
- substitution.
-
-Fri Dec 8 11:52:38 NST 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * var.c: ifdef'd HISTFILE, HISTSIZE stuff with HISTORY (was KSH).
-
- * *.c,*.h: ifdef'd coprocess stuff with KSH.
-
-Thu Dec 7 14:41:06 NST 1995 Michael Rendell (michael@angel.cs.mun.ca)
-
- * options.h(BRACEEXPAND): changed to BRACE_EXPAND; changed all
- references.
-
-Thu Dec 7 13:54:20 NST 1995 Michael Rendell (michael@angel.cs.mun.ca)
-
- * exec.c(do_selectargs): don't print newline on eof.
-
-Thu Dec 7 10:23:30 NST 1995 Michael Rendell (michael@angel.cs.mun.ca)
-
- * c_ksh.c(c_print): added -f for OS2.
- * tree.h(DODIRSWP),eval.c: deleted define and all uses of it.
- * exec.c(scriptexec): ...
- * io.c(check_fd): set O_TEXT/O_BINARY flag for OS2.
- * main.c(main): set O_BINARY/O_TEXT, search path for arg.
- * emacs.c(compl_file): call opendir with buf, not dirnam.
- (based on changes from Dale DePriest).
-
-Wed Nov 29 15:50:36 NST 1995 Michael Rendell (michael@angel.cs.mun.ca)
-
- * eval.c(expand,debunk): handle extended pattern matching stuff.
- * eval.c(debunk): now has two arguments, changed all calls.
- * eval.c(globit): changed to use has_globbing.
- * eval.c(copy_non_glob): deleted.
-
- * misc.c(has_globbing): new function.
- * misc.c(cclass): changed argument to unsigned char *; handle
- extended pattern matching.
- * misc.c(do_gmatch): new function (taken from gmatch()).
- * misc.c(gmatch): changed to call do_gmatch.
- * misc.c(do_gmatch): added cases for extended pattern matching
- (*(foo|bar), etc.).
- * misc.c(pat_scan): new function.
-
- * lex.c(yylex): added SPATTERN case.
-
- * lex.c(arraysub): changed to assume just past the leading [
- (was assuming about to read [); changed all calls; changed
- to use getsc_bn().
-
- * lex.c(ungetsc): added argument; changed all calls; can now unget
- arbitrary number of characters.
- * lex.c(ungetsc_): new function.
-
- * lex.h(struct source): added start field, removed u.start field,
- changed all uses.
- * lex.c(getsc_): case STTY: skip blank line only if this is first line
- of a command (eg, not part of here documennt, etc.).
-
- * lex.c(yylex): case SHEREDELIM,SHEREDQUOTE: ignore \newline.
- * lex.c(readhere,get_brace_var): ignore \newline.
- * lex.c(getsc_bn,getsc_bn_): new define/function.
-
- * exec.c(iosetup): don't enforce noclobber for non-regular files.
-
- * tree.h(OPAT,SPAT,CPAT): new defines.
- * tree.c(tputS,wdscan): added cases for OPAT,SPAT,CPAT.
-
- * lex.c(yylex): moved case '[' from Subst: switch to case SBASE:.
-
-Tue Nov 14 11:00:48 NST 1995 Michael Rendell (michael@angel.cs.mun.ca)
-
- * syn.c(get_command,caselist): moved parsing of IN/ESAC into
- caselist; allow {/} instead of IN/ESAC;
- * syn.c(casepart): new parameter: endtok.
- * lex.c(yylex): allow } as well as ESAC when ESACONLY set.
- (changes based on fix from DaviD W. Sanderson).
-
-Tue Nov 14 10:22:17 NST 1995 Michael Rendell (michael@angel.cs.mun.ca)
-
- * main.c(shell): do not zero exstat at start of routine.
-
- * exec.c(execute): removed redundent "exstat = rv" before
- unwind(LERROR).
-
-Thu Nov 9 15:01:54 NST 1995 Michael Rendell (michael@angel.cs.mun.ca)
-
- * var.c(arrayname): made argument const.
- * var.c(typeset): made var argument const.
- * var.c(export): made val argument const.
- * tree.c(wdscan): changed return type to non-const (added casts).
-
-Thu Nov 9 14:39:49 NST 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * c_ksh.c(c_alias),c_sh.c(c_set): made args[] array const.
- * c_ulimt.c(c_ulimit): made limits[] array const.
- * edit.c(x_mode): x_cur_mode no longer explicitly initialized to 0.
- * emacs.c(x_tab,x_atab): no longer explicitly initialized to 0.
- * exec.c(comexec): made texec non-static, non-initialized.
- * history.c(hist_finish): once no longer explicitly initialized to 0.
- * io.c(maketemp): io no longer explicitly initialized to 0.
- * jobs.c(job_list,last_job,async_job,free_jobs,free_procs): no longer
- explicitly initialized to 0.
- * jobs.c(lookup_msgs[],tt_sigs[]): made array const.
- * mail.c(mplist,mbox,mlastchkd,mmsgs): no longer explicitly
- initialized to 0.
- * vi.c(expand_word,complete_word): buf no longer explicitly
- initialized to 0.
- * vi.c(classify[]): made array const.
-
-Tue Nov 7 11:08:01 NST 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * mkman: new script
- * Makefile.in: use mkman to generate ksh.1
- * ksh.Man,ksh.1: renamed ksh.1 to ksh.Man
- * ksh.Man: changed way sh/ksh option handled.
- (changes based on fix from Michael Haardt).
-
-Tue Sep 19 09:53:53 NDT 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * jobs.c(j_stopped): deleted function.
- * jobs.c(j_exit): send SIGCONT, then SIGHUP; send SIGHUP if
- job is in foreground.
- (based on fix from Paul Borman)
-
- * Makefile.in: move .PRECIOUS to after all.
-
-Wed Sep 13 15:00:22 NDT 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * exec.c(dbteste_getopnd): changed tests from TO_STLT/TO_STGT
- to TO_STEQL/TO_STNEQ.
-
-Thu Aug 31 11:54:02 NDT 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * jobs.c(exchild): if fork fails, allow user to ^C out of loop.
-
-Tue Aug 29 09:40:37 NDT 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * exec.c(iosetup): don't do globing if not interactive (POSIX).
-
- * exec.c(iosetup): print <& or >& as appropriate in error message.
-
- * tree.h(IONAMEXP): new define.
- * tree.c(pioact): handle IONAMEXP.
- * exec.c(iosetup): set IONAMEXP.
-
- * io.c(savefd): added noclose parameter; changed all calls.
- * exec.c(iosetup): move call to savefd() to after the open();
- re-arranged the dup'ing (failed dups reported).
-
- * main.c(shell): call quitenv() before internal_error().
-
-Sun Aug 13 21:38:44 NDT 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * sh.h(ksh_sigsetjmp,ksh_siglongjmp): new defines; changed
- all uses of setjmp/longjmp to these.
- * configure.in: added checks for sigsetjmp() and _setjmp().
-
-Wed Jul 26 10:08:23 NDT 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * c_ulimit.c(c_ulimit): added -p ("maxproc", RLIMIT_NPROC)
- (fix from Simon J. Gerraty).
-
-Thu Jun 29 10:22:51 NDT 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * edit.c(promptlen): added spp parameter; changed all calls.
- * vi.c(prompt_skip): new variable.
- * vi.c(edit_reset): set prompt_skip; use prompt_skip in all calls
- to pprompt().
-
-Sat Jun 24 15:55:03 NDT 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * IAFA-PACKAGE: new file.
- * Makefile.in: added IAFA-PACKAGE to DISTFILES.
-
-Mon Jun 19 10:04:52 NDT 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * main.c(initcoms[]): added EXTRA_INITCOMS.
-
-Fri Jun 16 12:33:10 NDT 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * exec.c(search_access1): use FILECMP() instead of strcmp().
-
- * sh.h(FIELCHCONV): OS2 version: added isascii().
- * misc.c(gmatch); took unsigned out again for sc and pc.
-
- * main.c(main): don't set PS1 if it's already set; set it if
- we are root and prompt doesn't contain a #.
-
diff --git a/bin/pdksh/ChangeLog.0 b/bin/pdksh/ChangeLog.0
deleted file mode 100644
index 23dc38eb028..00000000000
--- a/bin/pdksh/ChangeLog.0
+++ /dev/null
@@ -1,3589 +0,0 @@
-$OpenBSD: ChangeLog.0,v 1.1 1996/08/14 06:19:10 downsj Exp $
-
-Thu Jun 15 11:02:06 NDT 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * made pdksh-5.2.3 distribution
-
- * c_ksh.c(c_whence): search keyword table if vflag set.
-
- * tree.h(DOVACHECK): new define.
- * eval.c(expand): check DOVACHECK flag.
- * exec.c(execute): when calling eval(), or in t->evalflags.
- * syn.c(get_command): set evalflags to DOVACHECK instead of DOASNTILDE.
-
-Wed Jun 14 09:27:19 NDT 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * c_ksh.c(c_cd): two argument format: use current_wd, not path
- when appending elen bytes.
- (fix from Gabor Zahemszky).
-
-Tue Jun 13 15:54:11 NDT 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * history.c(c_fc): if last not specified and !-l, use first as last.
-
- * eval.c(maybe_expand_tilde): allow CSUBST to end tilde word.
-
- * misc.c(gmatch): made sc and pc unsigned.
-
-Fri Jun 2 11:55:40 NDT 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * configure.in: added flock to AC_CHECK_FUNCS call.
- * conf-end.h: undef COMPLEX_HISTORY if !HAVE_FLOCK.
-
-Tue May 30 20:38:47 NDT 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * sh.h(SEEK_SET,SEEK_CUR,SEEK_END): define if not defined.
- * history.c: change L_XTND to SEEK_END.
-
-Tue May 30 17:01:34 NDT 1995 John Rochester (jr@panda.cs.mun.ca)
-
- * shf.c(shf_seek): new function.
- * shf.h(shf_seek): new prototype.
-
-Tue May 30 16:42:41 NDT 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * aclocal.m4(KSH_DEV_FD): new test.
- * acconfig.h(HAVE_DEV_FD): new define.
- * configure.in: call KSH_DEV_FD.
-
- * c_test.h(TO_FILAXST): new enum.
- * c_test.c(test_stat,test_eaccess): new functions for /dev/fd/n
- handling.
- * c_test.c(test_evalop): call test_stat() and test_eaccess()
- instead of stat() and eaccess() in most places; added case
- for TO_FILAXST.
-
-Tue May 30 16:06:21 NDT 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * aclocal.m4(KSH_MEMMOVE): fixed test so copies overlap.
-
-Sun May 28 11:11:03 NDT 1995 John Rochester (jr@panda.cs.mun.ca)
-
- * sh.h(safe_prompt): new variable.
- * main.c(initsubs): removed PS1.
- * main.c(main): initialize safe_prompt; initialize PS1 from
- safe_prompt.
- * lex.c(set_prompt): create new env while expanding PS1 - if expansion
- fails, use safe_prompt.
-
-Sat May 27 20:59:02 NDT 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * exec.c: put comments around token after #endif.
-
-Thu May 25 10:10:45 NDT 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * c_test.c(test_eval): case TO_OPTION: negate test if option starts
- with a !, always fail if option doesn't exist.
-
- * sh.h(FNOHUP): new define.
- * misc.c(options[]): "nohup" new option.
- * jobs.c(j_stopped,j_stopped_running): name of j_stopped changed
- to j_stopped_running; changed all calls; check for/warn about
- running jobs if appropriate.
- * jobs.c(j_exit): check for/kill running jobs if appropriate.
- * main.c(shell),c_sh.c(c_exit): un-ifdef JOBS the j_stopped_running()
- call and really_exit initialization/clearing.
-
-Wed May 24 10:06:14 NDT 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * options.h(DEFAULT_ENV): new define.
- * main.c(main): if ENV isn't set and DEFAULT_ENV is defined, include
- the later.
- (based on patches from Dave Kinchlea).
-
- * sh.h(LAEXPR): new define.
- * expr.c(evaluate): changed return type to error indicator; added
- rval and error_ok arguments; changed all calls (c_sh.c(c_shift),
- c_ulimit.c(c_ulimit),eval.c(expand),var.c(global,local)).
- * expr.c(v_evaluate): added error_ok argument; changed return value
- to error indicator; call unwind() if !error_ok.
- * expr.c(evalerr): changed errorf() to warningf(); call unwind(LAEXPR).
- * c_test.c(test_eval): merged code for integer operations to have
- two calls to evaluate().
-
- * io.c(warningf): print trailing newline; changed all calls.
-
- * history.c(hist_get): string search: use histptr, not histptr - 1.
-
-Tue May 23 11:07:50 NDT 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * sh.h(GI_NONAME): new define.
- * misc.c(ksh_getopts): honour GI_NONAME flag.
- * c_ksh.c(getopts_reset): set GI_NONAME flag.
-
- * exec.c(comexec): don't change $0 if FPOSIX flag set.
-
- * misc.c(ksh_getopt): don't use GI_DONE to allow parsing past
- bad options.
- * sh.h(GI_DONE): deleted define.
-
- * var.c(unset): added array_ref parameter; unset/free whole array
- if not an array_reference; changed all calls.
- * c_sh.c(c_unset): set array_ref parameter if there is a [ in the name.
-
-Mon May 22 10:33:14 NDT 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * history.c(hist_init): complex version: initialize hist_source
- (fix from Simon J. Gerraty).
-
-Sat May 20 11:06:15 NDT 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * made pdksh-5.2.2 distribution
-
- * Makefile.in: added c_test.h to HDRS.
-
-Fri May 19 12:35:18 NDT 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * made pdksh-5.2.1 distribution
-
- * emacs.c(v_version): ignore typed character if it is a space.
- * emacs.c(x_emacs_keys): bind <ESC>erase-char to delete-back-word
- (was delete-back-char).
- * emacs.c(x_defkeybindings[]): bound list-file to ^X^Y and
- newline-and-next to ^O, as per man page.
-
- * c_ksh.c(c_whence): changed "is a keyword" to "is a reserved word".
-
- * sh.h: changed SVSV_PGRP to SYSV_PGRP.
-
- * vi.c(vi_cmd): uncommented case for ^[ to make it easy to enable
- completion.
-
-Mon May 15 15:25:22 NDT 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * history.c(c_fc): accept -40 as -- -40.
- * main.c(initcoms[]): take -- out of history alias.
-
- * vi.c(print_expansions): handle trailing slash correctly (don't
- print empty strings).
-
- * c_ksh.c(c_cd): put back ksh_get_wd() call for os/2.
-
- * misc.c(ksh_get_wd): changed buf to b in call to getcwd().
-
-Tue May 9 13:57:31 NDT 1995 Michael Rendell (michael@dragon.cs.mun.ca)
-
- * c_test.h: new file.
- * c_test.c: major code restructuring: common parsing/evaluation
- routines call/called-by three sets of routines: one for
- normal test (and [..]), one for parsing [[ .. ]] one for
- evaluating [[ .. ]].
- * c_test.c(oexpr,aexpr,nexpr,primary,is_op): renamed to test_oexpr,
- test_aexpr, test_nexpr, test_primary, test_isop.
- * c_test.c(eval_unop,eval_binop): combined into new test_eval function.
- * c_test.c(syntax): renamed to ptest_error,
- * c_test.c(ptest_isa,ptest_getopnd,ptest_eval): new functions.
- * syn.c(syntaxerr): added extra arg; changed all calls.
- * syn.c(db_parse,db_oaexpr,db_nexpr,db_primary): deleted.
- * syn.c(dbtestp_isa,dbtestp_getopnd,dbtestp_eval,dbtestp_error): added.
- * syn.c(get_command): case DBRACKET: changed to call new routines.
- * tree.c(ptree): case DBRACKET: changed.
- * exec.c(execute): case DBRACKET: changed.
- * exec.c(dbteste_isa,dbteste_getopnd,dbteste_eval,dbteste_error): added.
-
-Fri May 5 17:10:23 NDT 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * emacs.c(compl_file,compl_command): fixed buffer growing code.
-
-Thu May 4 22:44:01 NDT 1995 Michael Rendell (michael@garfield.cs.mun.ca)
-
- * aclocal.m4(KSH_UNISTD_H): include <sys/types.h> and only include
- <dirent.h> if HAVE_DIRENT_H is defined.
-
-Thu May 4 21:19:15 NDT 1995 Michael Rendell (michael@garfield.cs.mun.ca)
-
- * c_ksh.c: include "ksh_stat.h".
- * c_ksh.c(c_cd): don't do physical chdir if S_ISLNK not defined.
-
-Wed May 3 10:08:32 NDT 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * made pdksh-5.2.0 distribution
-
- * misc.c: include <ctype.h>.
- * misc.c(gmatch): added isfile argument; changed all calls.
- * sh.h(FILECHCONV): (os2 version) - use isupper.
- * emacs.c(strmatch): don't increment in FILECHCONV.
-
- * aclocal.m4(KSH_HEADER_SYS_WAIT): new macro.
- * configure.in: use KSH_HEADER_SYS_WAIT instead of AC_HEADER_SYS_WAIT.
- * ksh_wait.h: if POSIX_SYS_WAIT not defined, undef W* macros.
-
-Tue May 2 12:10:39 NDT 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * emacs.c,emacs-gen.sh,emacs-c.in,emacs.out,Makefile.in: changed emacs
- source munging to create emacs.out which is included by emacs.c
- rather then munging emacs.c itself.
-
- * lex.c(pprompt): flush shl_out.
-
- * vi.c(glob_word): if path has *?[, don't add * (was if last component).
-
- * emacs.c(x_search_char): renamed to x_search_char_forw.
- * emacs.c(x_search_char_back): new function; bound to ^[^].
-
- * sh.h: changed SVR3_PGRP to SYSV_PGRP.
- (fixes from Gabor Zahemszky).
-
-Tue May 2 10:09:57 NDT 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * c_ksh.c(c_cd): deleted OS2 ifdefs.
- * path.c(make_path): use ISRELPATH instead of ISABSPATH
- * path.c(simplify_path): use ISROOTEDPATH instead of ISABSPATH.
- * sh.h(ISABSPATH,ISROOTEDPATH,ISRELPATH): changed/new defines.
-
- * aclocal.m4(AC_LANG_C,AC_LANG_CPLUSPLUS,AC_TRY_RUN): copied
- from autoconf's acgeneral.m4, changed to handle .exe suffix.
- * aclocal.m4(KSH_OS_TYPE): os2 case: set $ac_exe_suffix.
- * configure.in: substitute ac_exe_suffix.
- * Makefile.in: changed references to E to exe_suffix, set to
- ac_exe_suffix
-
- * c_ksh.c(c_cd): ifdef S_ISLNK second use of get_phys_path().
- * edit.c(x_mode): removed ifndef OS2.
- (fixes from Dale DePriest)
- * exec.c(search_access1): add .sh to suffix lists.
- * vi.c(vi_insert,vi_hook): OS2: changes to allow arrow keys work
- in insert mode.
-
-Mon May 1 16:28:44 NDT 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * path.c(ksh_get_wd): getcwd() case, return alloc'd buffer, not
- a malloc'd one.
-
-Mon May 1 09:41:56 NDT 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * aclocal.m4: changed HAVE_SYS_RESOURCES_H to HAVE_SYS_RESOURCE_H.
-
- * aclocal.m4(KSH_OS_TYPE): new macro.
- * aclocal.m4(KSH_OS2_EMX): deleted.
- * configure.in: deleted calls to AC_AIX,AC_MINIX,AC_ISC_POSIX,
- KSH_OS2_EMX; replaced with KSH_OS_TYPE.
- * acconfig.h(OS_ISC,OS_SCO): new undefs.
- * sh.h: changed use of isc386 to OS_ISC
- * edit.c: changed use of M_UNIX to OS_SCO.
-
-Sat Apr 29 21:10:54 NDT 1995 Michael Rendell (michael@garfield.cs.mun.ca)
-
- * vi.c(glob_word): don't append * if there are unescaped globing
- characters in the last component of the filename; some redundent
- code eliminated.
- (based on fix from Michael Jetzer).
-
-Fri Apr 28 16:10:22 NDT 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * eval.c(globit): save/restore actual DIRSEP char - don't use DIRSEP.
-
- * c_ulimit.c: removed ARGS from declaration of ulimit to avoid
- portability problems (osf/1 has ulimit(int,...), os2 has
- ulimit(int,long)).
-
- * tty.c(tty_init): added __SCO__ defines to avoid opening /dev/tty.
-
- * configure.in,aclocal.m4,acconfig.h: added KSH_OS2_EMX test.
- * os2/config.h, os2/configure.cmd, os2/make.sed: updated for new
- autoconf.
-
-Tue Apr 25 12:20:45 NDT 1995 Michael Rendell (michael@dragon.cs.mun.ca)
-
- * configure.in: added sys/param.h test; changed getcwd test to getwd.
- * c_ksh.c(c_pwd): new function.
- * sh.h(current_wd, current_wd_size): new variables.
- * c_ksh.c(c_cd): changed to handle -L, -P.
- * main.c(main): use set_current_wd when setting $PWD;
- instead of changing to / when can't get pwd, print warning;
- deleted pwd alias; don't make PWD and OLDPWD reaedonly.
- * path.c(simplify_path): changed to handle relative paths.
- * path.c(make_path): added phys_path argument to support cd -P.
- * path.c(set_current_wd,get_phys_path,do_phys_path): new functions.
- * misc.c(ksh_get_wd): new function.
- * missing.c(getcwd): deleted.
- * misc.c(options[]),sh.h: added "physical", FPHYSICAL.
-
-Mon Apr 24 14:33:03 NDT 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * shf.c(shf_smprintf): new function.
-
- * expand.h(Xsize): new define.
-
-Fri Apr 21 21:22:44 NDT 1995 Michael Rendell (michael@garfield.cs.mun.ca)
-
- * sh.h: changed SIZEOF_long to SIZEOF_LONG.
- * exec.c(scriptexec): if OS2 ifdefed code, changed ISDIRSEP to
- explicit /.
-
-Thu Apr 20 21:18:12 NDT 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * history.c(hist_get) if n < 0, use n + 1 to account for histbackup().
-
- * lex.c(set_prompt): added source argument; changed all calls;
- changed to do ! and !! substitutions when setting PS1.
- * lex.c(pprompt): ifdef'd out code to deal with ! and !!.
-
- * shf.c(shf_puts): new routine.
- * exec.c(herein), lex.c(getsc_): changed to use shf_puts.
-
-Thu Apr 20 15:50:35 NDT 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * siglist.sh: clear traps in subshell to cover for bug in bash 1.4.3
- (based on fix from Fritz Heinrichmeyer).
-
-Wed Apr 19 12:04:59 NDT 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * vi.c(classify): cleaned up table; filled in U_ flag for commands
- that don't modify things.
- * vi.c(first_insert, saved_inslen): new variables.
- * vi.c(vi_reset): don't reset yanklen, inslen, lastcmd, lastac;
- set first_insert, saved_inslen.
- * vi.c(vi_insert): added code to handle first insertion to allow
- redoing commands from last edit.
- (based on fixes from Michael Jetzer).
-
- * vi.c(VVERSION): new state.
- * vi.c(classify): cleared C_ flag for 032 (^Z); set it for ^V.
- * vi.c(nextstate): added VVERSION.
- * vi.c(vi_hook): cases for VVERSION.
- * sh.h(ksh_version): new declaration; removed declaration from
- all other files.
-
- * Makefile.in: removed rcs-ci, rcs-diff targets; put RCSFILES
- into DISTFILES and removed former.
-
- * var.c(newblock): copy argc/argv from previous env if it exists.
-
-Tue Apr 18 23:10:32 NDT 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * jobs.c(exchild): report internal error if execute() returns in child.
- * exec.c(execute): case TASYNC: clear exec flag in call to execute().
-
-Tue Apr 18 12:05:23 NDT 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * emacs.c(x_bind): added list argument.
- * c_ksh.c(c_bind): added -l (list) option.
-
- * emacs.c,emacs-c.in: moved emacs.c to emacs-c.in.
- * Makefile: add rule to create emacs.c from emacs-c.in.
- * emacs-gen.sh: new file.
- * emacs.c(struct x_defbindings, x_defbindings[]): new struct/array.
- * emacs.c(struct x_ftab, x_ftab[]): removed x_db_tab, x_db_char;
- initialize x_ftab[] via script.
- * emacs.c(x_init_emacs): changed to load key bindings from
- x_defbindings.
- * emacs.c(Findex): added typedef.
- * emacs.c(x_tab[]): changed to index into x_ftab; changed all refernces.
- * emacs.c(xft_*): changed to XFUNC_*.
- * emacs.c(XF_PREFIX): new flag, used for x_meta1, 2, 3.
- * emacs.c(KPREF,KNULL): deleted (no functional use), changed
- references to KSTD.
- * emacs.c(x_last_command): changed type to Findex.
- * emacs.c(x_emacs): set x_last_command to 0 at start; removed
- same from case KEOL.
-
- * emacs.c(XF_ARG): new flag for struct ftab.
- * emacs.c(x_ftab[]): filled in XF_ARG for appropriate commands.
- * emacs.c(x_arg_defaulted): new variable.
- * emacs.c(x_emacs,x_set_arg): set x_arg_defaulted.
- * emacs.c(x_bword, x_fword,x_fold_case): removed use of x_last_command.
- * emacs.c(x_fold_upper,x_fold_lower,x_fold_capitailze): trivial
- functions that call x_fold_case; changed x_ftab[] to use these
- instead of x_fold_case so arbitrary keys can be bound to them.
- * emacs.c(x_fold_case): changed to assume argument is 'L', 'U', or 'C'.
- * emacs.c(x_del_back,x_del_char,x_prev_histword,x_prev_com,x_next_com,
- x_kill,x_insert): use x_arg and x_arg_defaulted.
- * emacs.c(x_delete): don't change mark point (xmp) if <= cp; added
- force_push argument; changed all calls.
-
-Mon Apr 17 10:30:12 NDT 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * emacs.c(x_e_getc): changed to handle macroptr, ungetting characters.
- * emacs.c(x_e_ungetc): new function.
- * emacs.c(x_emacs): let x_e_getc() take care of macroptr.
- * emacs.c(x_version,x_search_hist): use x_e_ungetc() instead of
- macroptr.
- * emacs.c(x_set_arg): handle string of digits.
-
- * emacs.c(x_search_hist): handle deleting chars from search string.
- (fix from Dale DePriest)
- * emacs.c(x_search): added sameline paramater.
- * emacs.c(x_search_list): changes x_zots() to x_e_puts(); make
- deleting in empty pattern break out of search.
-
- * vi.c(domove): case '%': adjust ncursor forward only if matching
- opening bracket (so when cursor is on the B in "(fooBar)", c%
- changes the openbracket as well.
- * vi.c(vi_cmd): case y/d/c: special case to move end point ahead
- if move cmd is % and match was to the left of the cursor.
-
-Thu Apr 13 10:34:26 NDT 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * vi.c(complete_word): no bell on ambiguous matches (user can
- tell its ambiguous 'cause there is not space or slash appended)
-
- * configure.in,aclocal.m4: added KSH_MEMMOVE, KSH_MEMSET tests
- to fix problems with compiler builtins.
-
- * misc.c(blocking_read, reset_nonblock) new routines.
- * sh.h: deleted O_NONBLOCK ifdefs/defines.
- * main.c(main),lex.c(getsc_),edit.c(x_getc),shf.c(shf_fillbuf):
- use reset_nonblock().
- (fix based on code from John Rochester)
-
-Tue Apr 11 14:36:22 NDT 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * history.c(c_fc): mostly POSIXized.
- * history.c(hist_execute,hist_get_newest,hist_get_oldest): new routines.
- * history.c(hist_get,histget): changed histget to hist_get.
- * history.c(hist_replace,histrpl): changed histrpl to hist_replace.
- * lex.h(SHIST,histpush): deleted; deleted all references.
- * history.c(histget): add approx check for history that hasn't
- happened yet.
-
- * misc.c(getn): allow leading plus (eg, +3).
-
- * main.c(initcoms[]): defined history as "fc -l --".
-
- * conf-end.h(JOBS): don't define if no posix or bsd process groups
- (was if SIGCONT not defined).
-
-Mon Apr 10 14:51:54 NDT 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * exec.c(comexec),c_ksh.c(c_getopts),c_sh.c(c_read): use FEXPORT flag.
-
- * ksh_wait.h: changed to work with autoconf 2.x AC_HEADER_SYS_WAIT -
- if sys/wait.h uses union wait, don't include it.
-
-Thu Apr 6 12:19:58 NDT 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * tty.c(tty_init): print warning if open of /dev/tty fails.
-
-Sat Mar 4 01:20:03 NST 1995 Michael Rendell (michael@garfield.cs.mun.ca)
-
- * io.c(maketemp): create valid dos filenames.
-
-Mon Feb 27 11:04:32 NST 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * Changed from autoconf 1.x to autoconf 2.x.
- * acconfig.h: included old config.h.top and config.h.bot.
- * config.h.top, config.h.bot: deleted; deleted all references.
- * install.sh: changed to install-sh; changed all references.
- * Makefile.in: use @CPPFLAGS@, @CFLAGS@, @LDFLAGS@;
- use @configure_input@; remove config.log and config.cache in
- distclean; use @prefix@ and @exec_prefix@.
- * ksh_dir.h: changed to use new autoconf defines; changed NLENGTH()
- to NAMLEN(); changed all references.
-
-Mon Feb 27 9:31:02 NST 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * sh.h(ISABSPATH): new macro.
- * var.c(setspec): use ISABSPATH() when setting tmpdir.
-
- * emacs.c(compl_file): added OS2 ifdefs.
- * exec.c(scriptexec): OS2: ignore path specified in #! scripts.
- * sh.h(ksh_dupbase): OS2: now same as unix.
- * trap.c(sigtraps[],inittraps): remove OS2 defines.
- * trap.c(alarm_catcher): V7_SIGNALS: use sig, not i.
- (Fixes from Dale DePriest)
-
-Mon Feb 27 10:06:00 NST 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * configure.in: test for resource.h.
- * c_ulimit.c: include ksh_time.h instead of sys/time.h; use
- HAVE_SYS_RESOURCE_H when including sys/resource.h
- (was HAVE_SETRLIMIT).
- * aclocal.m4(KSH_RLIM_T): check sys/resources.h for rlim_t.
-
-Fri Feb 24 17:30:16 NST 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * vi.c(struct macro_state, macro): new structure/variable.
- * vi.c(vi_hook, vi_cmd): use macro state info to allow nested macros,
- detect recursive macros.
-
-Wed Feb 22 21:20:43 NST 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * c_ksh.c(c_whence): "an export" instead of "a export".
- * vi.c(classify[]): added @<char>.
- * vi.c(vi_hook,vi_cmd): added support for @<char> (macros).
- (fixes from Frank Edwards).
-
-Sun Feb 19 11:57:20 NST 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * exec.c(comexec): case CFUNC: use cp (not tp->name) when checking if
- an autoloaded function was defined; save/restore kshname before/after
- function call.
- * var.c(popblock): don't set kshname to e->loc->argv[0] - it isn't
- always right.
-
-Fri Feb 10 12:36:16 NST 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * misc.c(parse_args): check OF_SET when building set_opts (was
- checking OF_CMDLINE).
-
- * conf-end.h(JOBS): don't define if SIGCONT not defined.
-
- * sh.h(FLOGIN) new enum.
- * misc.c(options[],parse_args): added login option; set FLOGIN if
- name in argv[0] starts with -.
- * main.c(main): use FLOGIN flag; changed the way OS2 code looks
- for profile.
-
-Wed Feb 1 09:55:40 NST 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * expr.c(varsub): in FUNSET test, don't always fail # and %
- substitutions (test for unset variable).
-
-Wed Jan 25 09:22:15 NST 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * sh.h(MIN_COLS): new define.
- * sh.h(MIN_EDIT_SPACE): new define.
- * vi.c(prompt_trunc): new variable.
- * vi.c(edit_resize): calculate how much of prompt to truncate.
- * lex.c(pprompt): added new argument; changed all calls.
- * lex.c(yylex),emacs.c(x_emacs),vi.c(x_vi): move pprompt() inside
- x_emacs(), x_vi() or just before read in yylex().
-
-Tue Jan 24 12:35:18 NST 1995 Michael Rendell (michael@panda.cs.mun.ca)
-
- * misc.c(parse_args): changed arrayname variable to array.
- * var.c(basename): changed name of function to arrayname();
- changed all references (Based on fix from Dan Quinlan).
-
-Fri Dec 30 10:34:50 NST 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * ksh.1: modifications to generate two man pages: sh and ksh
- (Fixes from Michael Harrdt).
-
-Wed Dec 28 16:55:13 NST 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * vi.c(complete_word): don't check for globing characters.
-
-Wed Dec 28 10:32:18 NST 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * exec.c(search_access1): don't use ret variable; move "." to end
- of xsuffixes/rsuffixes.
- * os2.c(_execve): OS2: fixed typo.
- * sh.h(FILENCMP): changed stricmp to strnicmp.
- * os2/config.h: added define for rlim_t.
- * os2/make.sed: changed > null to > nul.
- * Makefile.in(dist): generate os2/makefile after running Dist-fixup.
- (Fixes from Dale DePriest)
-
-Thu Dec 22 15:06:06 NST 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * made pdksh-5.1.3 distribution
-
- * *.c: removed RCSids.
-
-Wed Dec 21 11:55:01 NST 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * table.h(struct tbl): changed array field to union of array/fname;
- changed all references.
- * c_ksh.c(c_whence): print undefined function path.
- * exec.c(comexec): do autoloading of undefined functions; print
- error if function can't be found.
- * exec.c(findcom): fill in tp->u.fname for undefined functions;
- search FPATH if search of PATH fails.
- * table.h(FC_NOAUTOLOAD): deleted define; removed all references.
-
-Tue Dec 20 14:16:16 NST 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * exec.c(herein): check if name is null.
- * lex.h(HEREDELIM,SHEREDELIM,SHEREDQUOTE): new defines.
- * lex.c(yylex): added code for HEREDELIM.
- * syn.c(synio): use HEREDELIM.
- * lex.c(readhere): changed to allow \n in here-delimiter.
-
- * tree.c(tputS): quote ", ` and $ inside "-quotes.
- * tree.c(ptree,pioact): made static.
- * tree.c(ptree,fptreef,vfptreef): added indent argument; changed to
- use indent argument; changed all calls.
- * tree.h(struct ioword): added delim field.
- * tree.c(iocopy),syn.c(synio,syntaxerr): deal with delim field.
- * tree.c(pioact): print contents of here documents.
-
- * c_ksh.c(c_typeset): typeset -f foo: set exit code to 1 if function
- not found.
-
-Mon Dec 19 15:14:02 NST 1994 Michael Rendell (michael@garfield.cs.mun.ca)
-
- * history.c(histinit): increment line number for each history line.
-
- * exec.c(iosetup): OS2: if open /dev/null fails, try nul instead.
- * Makefile.in(debugtools,install,uninstall): make check-pgrp last;
- use $E.
- * eval.c(eval,expand): OS2: added DODIRSWP code.
- * main.c(main): OS2: only include $HOME/kshrc.ksh if interactive.
- * sh.h(FILENCMP,FILECMP,FILECHCONV): new defines.
- * misc.c(gmatch),vi.c(grabsearch,complete_word),emacs.c(compl_file):
- OS2: case insensitive compares.
- (fixes from Dale DePriest).
-
-Mon Dec 19 09:54:42 NST 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * vi.c(vi_cmd): make ~ honour argcnt (fix from Troy Bollinger).
-
- * vi.c(complete_word): don't add trailing / if there is already one.
- * vi.c(glob_word): return rval, not 0.
-
-Thu Dec 15 11:06:01 NST 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * vi.c(vi_cmd): call complete_word() with argument of 1 not 0.
-
-Tue Dec 13 12:07:50 NST 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * history.c(histget): made static; added approx argument; changed
- all calls.
-
-Tue Dec 13 10:58:14 NST 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * Makefile.in(mandir): use $(manext), not 1 (fix from Mike Long).
-
-Mon Dec 12 20:55:53 NST 1994 John Rochester (jr@panda.cs.mun.ca)
-
- * tree.c(ptree): print TELIF part of if statements
-
-Fri Dec 9 15:21:36 NST 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * trap.c(inittraps): OS2: don't trap SIGTERM (temproary fix).
-
- * exec.c(search_access1): OS2: fixed to check for valid suffix
- and change mode from X_OK to R_OK if appropriate.
-
- * edit.c: include <sys/stream.h>, <sys/ptem.h> for SCO unix
- (fix from William Bader).
-
- * c_ulimit.c(c_ulimit): changed type of val from long to rlim_t
- (fix from Thomas Gellekum and J.T.Conklin).
- * aclocal.m4(KSH_RLIM_T): new test for rlim_t.
- * configure.in: use KSH_RLIM_T.
- * acconfig.h: added rlim_t.
-
-Thu Dec 8 12:20:25 NST 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * expr.c(evalexpr): changed div-by-zero test to only derefernce vr
- if operation is a divide.
-
-Mon Dec 5 14:42:52 NST 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * exec.c(search): OS2: typo - changed namlen to namelen.
- * exec.c(search_access): OS2: check execute bit explicitly.
- * main.c(main): OS2: don't include ./profile.ksh.
- * options.h(DEFAULT_PATH): OS2: added /os2 to path.
- * sh.h(ksh_getdup): OS2: define to getdup(); prototype for getdup().
- * Makefile.in(dist): create os2 Makefile based on distribution
- Makefile.in.
-
-Mon Dec 5 12:17:14 NST 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * made pdksh-5.1.2 distribution
-
- * eval.c(globit): when searching directory, re-calculate end of
- string based on prefix length.
-
-Fri Dec 2 11:07:48 NST 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * syn.c(wordlist): if token isn't 'in', don't reject ;.
-
- * eval.c(expand): leading non-white-space IFS chars no cause initial
- empty field.
-
-Thu Dec 1 12:04:00 NST 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * made pdksh-5.1.1 distribution
-
-Thu Dec 1 10:50:38 NST 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * sh.h(TF_FATAL,fatal_trap): new define,variable.
- * trap.c(inittraps,trapsig,fatal_trap_check,trap_pending,runtrap,
- settrap): use TF_FATAL, fatal_trap.
- * trap.c(runtraps): changed argument from bool to TF_* flag; changed
- all calls.
- * jobs.c(j_waitj): check fatal_trap flag.
-
-Wed Nov 30 11:20:03 NST 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * conf-end.h: new file.
- * config.h.bot: moved guts to conf-end.h.
-
- * emacs.c(struct x_ftab): changed type of xf_db_char from char to int.
- * emacs.c(x_emacs): changed type of c from char to int.
- * emacs.c(X_NTAB): new define.
- * emacs.c(x_bind,x_init_eamcs): new X_NTAB, X_TABSZ.
- * emacs.c(x_prefix3, x_meta3): ifdef OS2.
- * emacs.c(x_bind): ifdef OS2; mask *a1 with CHARMASK.
-
- * exec.c(search_access): new function.
- * exec.c(search): use search_access() instead of duplicating test.
- * exec.c(search,search_access1): ifdef OS2.
-
- * Makefile.in(OS2FILES): new macro.
- * Makefile.in(dist): add OS2FILES to distribution.
-
- * options.h(DEFAULT_PATH): ifdef OS2.
- * edit.c(x_getc,x_mode): ifdef OS2.
- * path.c(make_path): ifdef OS2.
-
-Tue Nov 29 16:51:35 NST 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * sh.h(EXECSHELL,EXECSHELL_STR): ifdef OS2.
- * exec.c(scriptexec): use EXECSHELL_STR (was "EXECSHELL").
-
- * trap.c(sigtraps[]): ifdef OS2.
- * lex.c(yylex): ifdef OS2.
- * misc.c(change_flag): ifdef OS2.
- * history.c(HISTFILE): ifdef OS2.
- * eval.c(homedir): ifdef OS2.
- * c_sh.c(shbuiltins[]): ifdef OS2.
-
- * sh.h(ksh_execve,ksh_dupbase): new defines.
-
- * jobs.c(exchild): ifdef use of nice.
-
-Tue Nov 29 12:32:26 NST 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * eval.c(globit,copy_non_glob): changed to pass/use &xp it can change
- (memory can be re-allocated).
-
- * ksh_dir.h(NLENGTH): new macro.
- * eval.c(globit): use NLENGTH macro.
-
- * alloc.c(aresize): removed redundent np and optr variables.
-
-Mon Nov 28 14:55:49 NST 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * config.h.bot(HISTORY): new define.
- * lex.c(getsc_): ifdef HISTORY.
- * history.c: ifdef HISTORY (dummy histsave, init_histvec and
- hist_finish routines).
- * c_ksh.c(kshbuiltins): c_fc: ifdef KSH
- * lex.h(HISTORY): changed to HISTORYSIZE; changed all references.
-
- * options.h(KSH): new define.
- * config.h.bot: changed to deal with KSH define.
- * exec.c(do_select,pr_menu): ifdef KSH.
- * exec.c(execute): case TSELECT: ifdef KSH.
- * c_ksh.c(c_whence,c_command,kshbuiltins[]): ifdef KSH.
- * main.c(initcoms[],main): ifdef some aliases, SECONDS/RANDOM/TMOUT.
- * syn.c(get_command): case TDBRACKET: ifdef KSH.
- * syn.c(db_parse,db_aoexpr,db_nexpr,dp_primary): ifdef KSH.
- * syn.c(tokentab[]): "select", "[[" ifdef KSH.
- * var.c(special,getspec,setspec,unsetspec): ifdef KSH.
- * ksh.1: ifdef KSH; misc fixups.
- (changes mostly from Michael Haardt).
-
-Mon Nov 28 14:27:34 NST 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * var.c(skip_varname,special,global,local), table.c(hash,tsearch,
- tenter): made argument and return value const.
-
- * main.c(version_param[]): new variable.
- * main.c(initcoms[],main): use version_param instead of "KSH_VERSION".
-
- * history.c(histsave): EASY_HISTORY: changed to take same arguments
- as COMPLEX_HISTORY histsave(); changed all calls, removing
- unneeded ifdefs.
-
- * vi.c(x_vi), emacs.c(x_emacs): changed unwind() call from LINTR
- to LSHELL so newline isn't printed twice - also lets runtrap()
- set the exit code.
-
- * vi.c(vi_cmd): increment source line if saving to history.
-
-Fri Nov 25 14:43:57 NST 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * syn.c(get_command): don't generate a syntax error if EOF is read.
-
- * configure.in: add LDSTATIC to LDFALGS if the former is set.
-
- * history.c(hist_skip_back): start at the end of the buffer, not
- one past the end (fix from Simon J. Gerraty).
-
-Thu Nov 24 09:53:49 NST 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * syn.c(get_command,dogroup): allow { ...;} to be used instead
- of do ...;done in for/select loops.
-
-Wed Nov 23 09:09:43 NST 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * made pdksh-5.1.0 distribution
-
- * var.c(setspec): set seconds to current time - assigned value,
- not just current time.
-
- * emacs.c(x_copy_arg): deleted ifdef'd out code (x_prev_histword()
- does what it was supposed to do).
-
- * emacs.c(compl_command): don't call list_stash() twice (happened
- if type == 2 and multi set).
-
-Tue Nov 22 10:26:13 NST 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * c_test.c(eval_unop): don't assume S_ISBLK, S_ISCHR, S_ISUID,
- S_ISGID are defined.
-
- * path.c(make_path): avoid addeding extra /'s in paths; avoid
- infinate loop if result buffer not big enough.
-
- * main.c(main): setting PWD: avoid calling setstr() with the
- current value of PWD.
-
- * var.c(typeset): set free_me to 0 if t is integer.
-
- * emacs.c(x_search_hist): added overflow checking to fixed sized
- buffers.
- * emacs.c(compl_file,compl_command): removed fixed sized buffers.
-
- * vi.c(x_vi), emacs.c(x_emacs): on interrupt, unwind instead of
- calling runtraps().
-
- * vi.c(vi_cmd): added 'g' command to goto the most recent command.
-
- * c_sh.c(c_read), c_ksh.c(c_print): always increment source->line when
- saving history.
-
-Mon Nov 21 10:45:34 NST 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * exec.c(do_selectargs): removed use of pmenu variable (redundent)
- use isspace() instead of IFS chars; include <ctype.h>.
-
- * aclocal.m4(KSH_TERM_CHECK): do not allow HAVE_TERMIOS_H check to
- succeed on ultrix (avoid type-ahead loss).
-
- * emacs.c(x_fword): cahnged loop to skip non word chars, then word
- chars (was the opposite).
-
- * main.c(shell): after error/interrupt/etc, reset an EOF if ignoreeof
- option is set.
-
- * vi.c(classify[]): changed space (040) from C_|U_ to M_
- (got broken in 5.0.10).
-
- * ksh_wait.h(ksh_waitpid): new define.
- * jobs.c(waitpid): moved define to ksh_wait.h; changed use of
- waitpid() to ksh_waitpid().
-
- * history.c(hist_skip_back),io.c(maketemp): use procpid instead of
- getpid().
-
-Fri Nov 18 16:08:09 NST 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * vi.c(FSHOW8): inverted meaning: now if set, do the M- stuff
- (done so 8 bit char sets work by default).
-
- * main.c(main): set exstat to 127 if command file can't be opened.
-
- * main.c(main): use argv[0] instead of kshname when deciding
- whether to include profiles.
-
-Fri Nov 18 14:25:11 NST 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * made pdksh-5.0.10.1 distribution
-
- * tty.h: deleted KSH_VDISABLE; moved _POSIX_VDISABLE stuff to edit.c.
- * edit.c(x_init): calculate value for vdisable_c.
- * edit.c(x_mode): use vdisable_c instead of KSH_VDISABLE.
-
-Thu Nov 17 12:09:13 NST 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * made pdksh-5.0.10 distribution
-
- * lex.c(getsc_),edit.c(x_getc): call runtraps(FALSE) if read is
- interrupted.
- * vi.c(x_vi),emacs.c(x_emacs): call runtraps(FALSE) (was TRUE).
-
-Wed Nov 16 09:48:54 NST 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * exec.c(execute,scriptexec): call __setostype(0)/(1) before/after
- execve() on ISC machines.
-
- * trap.c(trap_pending): new fuction.
- * jobs.c(j_waitj): use trap_pending(); return -<signal-number> if
- interrupted.
- * jobs.c(waitfor): added sigp argument; changed all calls.
- * c_sh.c(c_wait): use signal number set by waitfor() to set exit status.
-
- * shf.c(SHF_INTERRUPT): no longer calls intrcheck() - now sets
- error flag and returns EOF.
- * c_sh.c(c_read): re-arranged to have single shf_getc() call; if read
- interrupted and signal is fatal (fatal_trap_check()), make read
- return with appropriate exit code.
- * trap.c(fatal_trap_check()): new function.
- * trap.c(inittraps()): catch and cleanup on SIGHUP; don't force the
- setting of SIGINT,SIGQUIT,SIGTERM,SIGHUP.
-
- * table.c(tenter): changed to use strlen()/memcpy() instead of loops.
-
- * var.c(initvar): new function.
- * main.c(main): call initvar().
- * var.c(special): changed to use hash table for lookup.
-
- * main.c(main),syn.c(initkeywords): moved table initialization
- from main() to initkeywords().
-
-Tue Nov 15 10:01:20 NST 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * eval.c(copy_non_glob): new routine.
- * eval.c(globit): changed to use copy_non_glob() instead of strchr().
-
- * misc.c(cclass): if [..] pattern has no closing ], do literal
- compare of character with [ (used to always fail).
-
- * eval.c(globit): handle symbolic links in the check code.
-
- * configure.in: added check for lstat().
- * ksh_stat.h: defined lstat to be stat if lstat is not available.
-
- * exec.c(search): return Xclose() instead of Xstring().
-
-Mon Nov 14 16:28:41 NST 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * ksh_times.h: changed BROKEN_TIMES to TIMES_BROKEN.
-
- * c_test.c(syntax): removed \n from error messages.
-
- * eval.c(glob,globit): changed to use dynamicly allocated string
- instead of a fixed sized buffer.
-
-Thu Nov 10 10:47:55 NST 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * history.c(sethistsize): don't set size if new size is < 0; fixed
- offset calculation so histptr is not way beyond the end of array;
- if history is shrinking, save newest history back.
-
- * vi.c(vi_hook): case VSEARCH: call restore_cbuf() after \n or \r.
-
- * main.c(quitenv): call restfd() even if fd < 0 to re-close fd.
-
- * exec.c(execute): commented out code that set savefd[0/1] to -1
- if input/output was a pipeline.
-
- * missing.c(dup2_fixup): deleted function.
- * sh.h(dup2->dup2_fixup): deleted define.
- * io.c(ksh_dup2): new function; changed all dup2() calls to ksh_dup2().
-
-Wed Nov 9 11:11:31 NST 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * edit.h(struct edchars): added eof field.
- * edit.c(x_init): initialize eof fields.
- * vi.c(x_vi): changed ^D to edchars.eof.
- * vi.c(vi_cmd): make I/cc/S skip blanks.
-
- * history.c(histsave): EASY_HISTORY: use memmove() to copy pointers
- back one.
-
- * vi.c(vi_cmd): make G act the same as at&t ksh.
- * vi.c(ismeta,O_): deleted macros; removed all references to O_.
- * vi.c(classify[]): add ^X and ^F to command mode.
-
-Tue Nov 8 11:15:01 NST 1994 Michael Rendell (michael@arlene.cs.mun.ca)
-
- * main.c(initsubs[]): don't set SHELL.
-
- * vi.c(vi_cmd): added v command (start up vi).
- * vi.c(vi_hook): added case for vi_cmd() returning 2.
- * vi.c(grabsearch): set anchored flag if pattern starts with ^.
- (based on fixes from Michael Jetzer).
-
- * history.c(findhist): added anchored argument; changed all calls.
- * history.c(histget): start searching from histptr-1; changed to
- call findhist() to do searching.
- * history.c(c_fc): changed to print multiline commands correctly.
- (based on fixes from Michael Jetzer).
-
-Fri Nov 4 10:30:14 NST 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * lex.c(yylex): when pushing alias sources, allocate from existing
- source's area.
-
- * lex.c(struct source): added areap field.
- * lex.c(pushs): added area argument; changed all calls.
- * history.c(histrpl): changed constant sized hline[] to expandable
- string; removed hline/hsize parameters; changed all calls; put
- newline at end of string.
- * history.c(c_fc): changed to use dynamically sized buffer when reading
- commands; strip nulls after read.
- * history.c(histbackup): made static.
-
- * trap.c(block_pipe): if handler is SIG_DFL, change it to SIG_IGN.
-
- * lex.c(readhere): changed to allow eof after end-of-file marker
- (bug report from Andrew Moore).
-
-Thu Nov 3 09:09:39 NST 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * io.c(coproc_read_close,coproc_write_close): new functions.
- * c_sh.c(c_read): call coproc_read_close() when eof is read.
- * c_ksh.c(c_print): set PO_COPROC if fd is coproc.write; call
- coproc_write_close() if write fails due to EPIPE.
- * exec.c(iosetup): call coproc_write_close() after #>&p.
- * sh.h(EF_COPROC_DUPED): deleted.
- * sh.h(struct coproc): deleted isopen field.
- * io.c(cleanup_coproc): do not use isopen field.
- * c_sh.c(c_exec): deleted EF_COPROC_DUPED code.
- * exec.c(TCOPROC): don't set isopen; don't start new coprocess if
- old job exists and write pipe hasn't been closed.
-
- * misc.c(str_zcpy): new function.
- * lex.c(getsc_): made line[] buffer local/static; use str_zcpy()
- to fill line[].
- * history.c(c_fc): use local hline buffer instead of global line[];
- use str_zcpy() to fill hline[];
- * history.c(histrpl): added hline and hsize parameters; changed all
- calls.
- * history.c(hist_init): EASY_HISTORY: use local hilne buffer instead
- of global line[].
- * lex.h(line[]): deleted.
- * syn.c(compile): do not set s->str to null for STTY and SHIST.
-
-Wed Nov 2 11:48:36 NST 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * lex.c(getsc_): case SDDPAREN: set csstate before going to
- SPAREN state.
-
- * Makefile.in(RCSFILES): removed POSIX from list (now covered in
- man page).
-
-Tue Nov 1 09:27:46 NST 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * eval.c(comsub): save/restore source before/after compile().
-
- * c_ulimit.c(c_ulimit): allow value to be arithmetic expression
- (as per Korn book).
-
- * c_sh.c(c_read): call set_prompt() before printing prompt.
-
- * expr.c(v_evaluate): treat an empty expression as 0.
-
-Mon Oct 31 09:23:57 NST 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * vi.c(grabhist,grabsearch): check that history line doesn't overflow
- edit buffer.
-
- * history.c(hist_finish): (EASY_HISTORY) changed for-loop condition to
- prevent passing the end of history.
-
- * eval.c(expand): when stuffing MAGIC, cast c to char.
-
- * misc.c(strip_nuls): new function.
- * lex.c(getsc_): case STTY/SFILE/SSTDIN: call strip_nuls() after
- reading commands.
-
- * edit.c(set_editmode): reversed strstr() arguments - check for
- vi/emacs in $EDITOR/$VISUAL string.
-
- * syn.c(yyparse): allow EOF as well as newline after a command.
- * lex.c(getsc_): case SSTRING: don't fake newline
-
-Sun Oct 30 10:55:20 NST 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * c_ksh.c(c_print): echo: check for -n, -e and -E options.
-
- * exec.c(comexec): don't allow command -p if restricted.
-
-Fri Oct 28 10:24:48 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * var.c(typeset): in fake_assign code, was freeing t->val.s + t->type
- instead of t->val.s - now uses free_me variable instead of aflag.
-
- * Makefile.in(depend): change blank lines in depend output to sh.h
- so dumb make(1)s won't die.
-
- * mail.c: changed checking to use atime/mtime instead of size; changed
- struct mbox mb_size field to mb_mtime, changed all references.
-
- * main.c(shell): do not execute (or set the exit status for) a null
- command.
- * lex.c(readhere): read the newline after the eof marker.
-
-Wed Oct 26 09:11:08 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * eval.c(globit): added FMARKDIRS support.
-
- * emacs.c(x_ftab[]): added entries for ansi arrow key bindings.
-
- * exec.c(execute,iosetup): move tracing of redirections from
- execute() to iosetup() so expanded name can be printed.
-
- * exec.c(execute): case TDBRACKET: read was being called instead of
- test.
-
- * ksh_stat.h(S_ISCDF): new define.
- * c_test.c: added -H for context dependent files (HP bizarreness).
-
- * main.c(initcoms[]): added alias local=typeset.
-
- * Makefile.in(stamp-h,config.status): added double quotes CONFIG_FILES
- and LDSTATIC assignments for dmake.
- * aclocal.m4(KSH_SYS_SIGLIST): do something with sys_siglist so it
- isn't optimized away.
- * aclocal.m4(KSH_CLOCK_T): do extra check for clock_t in sys/times.h.
- * acconfig.h(CLOCK_T_IN_SYS_TIMES_H): new define.
- * sh.h(SIGNALS): use _SIGMAX if NSIG, _MINIX not defined.
- (fixes from Brian Campbell <brianc@qnx.com>)
-
- * emacs.c(x_transpose): changed behavior if FGMACS flag set
- (fix from <guy@netapp.com>).
-
-Tue Oct 25 17:11:58 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * tty.c(KSH_VDISABLE): new define.
- * edit.c(x_init): use KSH_VDISABLE.
-
-Tue Oct 25 09:55:09 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * made pdksh-5.0.9 distribution
-
- * c_ulimit.c(c_ulimit): changed SOFT, HARD from enum to defines
- to avoid problems with ancient compilers.
-
- * vi.c(CHAR_LEN,char_len): changed macro to function; added FVISHOW8
- support.
- * misc.c(options[]), sh.h(FVISHOW8): added FVISHOW8 option.
-
-Sun Oct 23 11:02:26 NDT 1994 Michael Rendell (michael@maple.cs.mun.ca)
-
- * main.c(shell): keep unwinding if LINTR and not interactive.
-
- * lex.c(yylex): do redumentery quote parsing for $(..).
-
-Thu Oct 20 11:02:27 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * exec.c(execute): case TSELECT: set rv to 1 if eof is read.
- * exec.c(execute): case TFOR/TSELECT/TWHILE/TUNTIL: set rv to 0 before
- entering loop, but after setjmp incase of a continue; rv to 0
- after a break.
- * exec.c(execute): case TFOR/TSELECT: do readonly check before
- assigning value.
- * c_ksh.c(c_getopts): do readonly check before assigning value.
-
- * misc.c(print_columns),c_ksh.c(kill_fmt_entry),
- misc.c(options_fmt_entry),exec.c(select_fmt_entry): new functions.
- * c_ksh.c(c_kill),misc.c(printoptions),exec.c(pr_menu): use
- print_columns() call a call-back routine to format information
- in columns.
-
-Wed Oct 19 10:26:25 NDT 1994 Michael Rendell (michael@arlene.cs.mun.ca)
-
- * misc.c(cclass): require MAGIC before - and ].
- * eval.c(expand): prefix - and ] with MAGIC if appropriate.
-
- * var.c(typeset): don't allow export flag of readonly variables
- to be cleared.
-
- * eval.c(globit): added call to intrcheck().
-
-Mon Oct 17 11:48:05 NDT 1994 Michael Rendell (michael@arlene.cs.mun.ca)
-
- * lex.c(readhere): check for and report write errors.
-
-Sun Oct 16 16:10:59 NDT 1994 Michael Rendell (michael@arlene.cs.mun.ca)
-
- * c_ksh.c(c_cd): don't allow cd if restricted.
- * exec.c(comexec): if restricted and command contains /, print error.
- * exec.c(ioestup): if restricted, don't allow file creations.
- * main.c(is_restricted): new function.
- * main.c(main): save and reset FRESTRICTED during .profile/ENV reading;
- set FRESTRICTED if argv[0] or SHELL refers to restricted shell;
- make PATH, ENV, SHELL readonly if restricted.
- * var.c(typeset): check for restricted shell and PATH/ENV/SHELL.
-
-Thu Oct 13 21:01:14 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * main.c(shell): only call j_notify() for interactive shells.
-
- * c_sh.c(c_read): check if variable is readonly before assigning
- value.
-
-Wed Oct 12 14:08:46 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * lex.h(COPROC),tree.h(TCOPROC,XCOPROC): added defines.
- * lex.c(yylex): return COPROC for |& token.
- * syn.c(tokentab): added COPROC.
- * syn.c(c_list): accept COPROC, create TCOPROC node.
- * tree.c(ptree): added case for TCOPROC.
- * exec.c(execute): added case for TCOPROC.
- * io.c(check_fd,get_coproc_fd): new functions.
- * c_sh.c(c_read),c_ksh.c(c_print): changed to use check_fd();
- added -p option; for c_print() ensure SIGPIPE doesn't kill shell.
- * exec.c(iosetup): changed to use check_fd() for IODUP; when
- checking fore close, require exactly the string '-', not any
- string starting with '-'; added strerror() to error message.
- * jobs.c(exchild): don't open /dev/null if XCOPROC; close
- coproc.read/write/childread in child if XCOPROC; don't pass
- XCOPROC flag on to execute(); set coproc.job to job in parent
- if XCOPROC.
- * jobs.c(check_job): clear coproc.job if said job dies.
- * trap.c(block_pipe,restore_pipe): new functions.
- * sh.h(struct coproc, EF_COPROC_DUPED): new structure and define.
- * c_sh.c(c_exec): if EF_COPROC_DUPED set, clean up co-process stuff.
-
- * main.c(cleanup_parents_env): new function.
- * jobs.c(exchild): call cleanup_parents_env() after fork().
-
- * tree.h(IORDUP): new define.
- * lex.c(yylex): changed redirection parsing to not accept & only after
- a single < or >; set IORDUP flag for x<&y; fixed <</<>/>> check to
- not allow >< (again).
- * tree.c(pioact): use IORDUP flag to print <& or >&.
-
- * jobs.c(exchild): set JF_ORIGFG flag if job started in foreground.
- * jobs.c(j_waitj): don't get default tty settings if JF_ORIGFG not
- set.
-
- * misc.c(parse_args): treat -A as a flag that is handled later
- (used to require argument); do array setting after argument
- sorting.
- * var.c(set_array): changed second argument from 0/1 flag to
- -1/1 flag; changed all calls.
-
-Thu Oct 6 11:55:27 NDT 1994 Michael Rendell (michael@arlene.cs.mun.ca)
-
- * table.c(tinit): added initial table size argument; call texpand
- if size isn't 0; changed all calls.
- * main.c(main): try to make sure table size is big enough for
- builtins and keywords (cut down on amount of re-hashing).
-
- * eval.c(expand): added next and prev fields to struct SubType;
- removed fixed length subtype array, changed code to allocate
- SubTypes as needed.
-
-Wed Oct 5 09:25:06 NDT 1994 Michael Rendell (michael@arlene.cs.mun.ca)
-
- * main.c(main): moved initio() above inittraps() as later can print
- stuff.
-
- * table.h(IMPORT): new flag.
- * var.c(typeset): if IMPORT flag set, don't allow array references,
- insist on assignment.
- * var.c(import): deleted function.
- * main.c(main): use typeset() instead of import().
-
- * sh.h: include expand.h.
- * expand.h(Xnleft): new define.
- * expand.h(struct XString, Xinit): added areap field; added area
- argument to Xinit; changed all calls.
- * lex.h(struct source): added xs field.
- * shf.c(shf_gets,shf_getse): changed name fromshf_gets to shf_getse;
- return pointer to null byte instead of start of buffer.
- * lex.c(pushs): if type is SFILE or SSTDIN, initialize s->xs.
- * lex.c(getsc_): case SFILE/SSTDIN: use s->xs instead of fixed
- size line buffer.
-
- * syn.c(compile): don't change s->str if SFILE.
- * main.c(main): call pushs() explicitly for each of SSTRING,
- SFILE, SSTDIN, STTY.
-
- * aclocal.m4(KSH_GCC_FUNC_ATTR): changed GCC_FUNC_ATTR to
- HAVE_GCC_FUNC_ATTR.
- * config.h.bot: changed use of GCC_FUNC_ATTR; deleted
- GCC_FA_NORETURN, GCC_FA_CONST, GCC_FA_FORMAT defines, created
- generic GCC_FUNC_ATTR define; changed all uses of GCC_FA_*.
-
- * main.c(main): set s->file for SSTDIN input.
-
- * main.c(shell): pass LERROR on if not interactive.
-
- * expand.h(Xcheck,XcheckN): added XcheckN define, changed Xcheck
- to use XcheckN; made XcheckN call Xcheck_grow_() do do any real work
- (to cut down on code size).
- * misc.c(Xcheck_grow_): new function.
- * exec.c(search),c_sh.c(c_read): changed to use Xstring() routines
- (used to use the fixed size buffer line[]).
- * exec.c(findcom): avoid re-saving search() result in ATEMP.
-
-Tue Oct 4 15:32:37 NDT 1994 Michael Rendell (michael@arlene.cs.mun.ca)
-
- * jobs.c(j_jobs): return int value indicating error/ok; changed
- all calls.
-
- * misc.c(getn): added int * argument to hold result; changed
- return value to indicate success/failure; changed all calls.
- * misc.c(bi_getn): new function.
- * misc.c(getn_): deleted function.
-
- * io.c(internal_error,error_prefix,warningf): new functions.
- * *.c: changed errorf() calls reporting internal errors to
- use internal_error() function; changed many shellf()s to
- warningf().
- * io.c(errorf),lex.c(yyerror): changed to use error_prefix().
-
- * alloc.c(aprint): ifdef'd out.
- * tree.c(phash): deleted function.
-
-Mon Oct 3 15:08:24 NDT 1994 Michael Rendell (michael@arlene.cs.mun.ca)
-
- * sh.h(kshname): new variable
- * main.c(main): changed name to kshname, deleted local variable.
- * exec.c(comsub): update kshname.
- * var.c(popblock): restore kshname.
- * io.c(errorf,bi_errorf): print shell name before error message.
-
- * c_ksh.c(c_cd): print new directory on stdout, not stderr.
-
- * sh.h(GI_MINUS): new define.
- * misc.c(ksh_getopts): changed so once - or + introduces option,
- all options must start with same character.
-
- * sh.h(builtin_argv0): new variable.
- * exec.c(call_builtin): set/clear builtin_argv0, builtin_flag; changed
- argument to a struct tbl *; changed all calls.
- * io.c(bi_errorf): new function.
- * c_ksh.c,c_sh.c,c_ulimit.c,emacs.c,history.c,jobs.c: changed all uses
- of errorf() to bi_errorf().
- * emacs.c(x_bind): changed return value to int; changed all calls.
- * history.c(histrpl): return 0 if there is an error; changed all calls.
- * misc.c(parse_args): use bi_errorf(); return -1 for error; changed all
- calls.
- * misc.c(ksh_getopts): call bi_errorf instead of errorf which means
- ksh_getopts() may return after an error, so changed all calls to
- check for '?' return.
-
- * exec.c(iosetup): use shellf() to report errors and return value
- indicating success or failure.
- * exec.c(execute): if iosetup fails, cause fatal error for special
- builtins, return otherwise; print PS4 and redirections.
-
-Fri Sep 30 15:17:37 NDT 1994 Michael Rendell (michael@arlene.cs.mun.ca)
-
- * c_ulimit.c(c_ulimit): accept unlimited as a valid value.
-
- * c_test.c(c_test): changed posix special case code to use
- while loop.
-
- * c_ksh.c(c_whence): for whence -p, don't look for built-ins or
- fuctions.
-
-Thu Sep 29 10:34:59 NDT 1994 Michael Rendell (michael@arlene.cs.mun.ca)
-
- * c_ksh.c(c_alias): added -r option so the sysv-bounre shell
- hash -r will work.
-
- * eval.c(debunk): use strchr() to find first MAGIC, if any.
-
-Wed Sep 28 15:34:32 NDT 1994 Michael Rendell (michael@arlene.cs.mun.ca)
-
- * sh.h(O_NONBLOCK): define to O_NDELAY or FNDELAY if not defined.
- * main.c(main): if stdin is O_NONBLOCK'd, clear O_NONBLOCK.
-
- * misc.c(options[], parse_args): make -c a normal flag, not an option
- with an argument (POSIX); deleted cargp argument to parse_args().
- * main.c(main): print error if -c and no arguments left.
-
- * lex.h(SSTDIN): new define.
- * lex.c(yylex): added case for SSTDIN.
- * main.c(main): if -s flag used, set source type to SSTDIN.
-
-Tue Sep 27 08:52:11 NDT 1994 Michael Rendell (michael@arlene.cs.mun.ca)
-
- * lex.c(get_brace_var): new function.
- * lex.c(yylex): removed most ${..} parsing - leave it to expand();
- use get_brace_var() to read the variable part of a ${..} expression.
- * tree.c(tputs,wdscan): case OSUBST: delete code that understood
- partially compiled ${..}.
- * sh.h(C_SUBOP,C_SUBOP1,C_SUBOP2): changed C_SUBOP to C_SUBOP1,
- added C_SUBOP2.
- * misc.c(initctypes): removed # and % from C_SUBOP; changed C_SUBOP to
- C_SUBOP1; added C_SUBOP2.
- * eval.c(varsub): look at word part of substitution to figure out
- type of substitution; check for bad substitutions; check for unset
- variables for #/% substitutions.
- * eval.c(struct SubType): changed type field to stype; changed quote
- field to short; added f field.
- * tree.h(DOTEMP_): new define.
- * eval.c(expand): case CSUBST: case '=': deleted bad substitution
- error (now handled in varsub); case OSUBST: removed special handling
- of trimming - varsub() does it now; when pushing/poping state (st),
- save/restore value of f; set f to DOPAT when trimming; case CSUBST:
- case '=': restore original position in string, substitute the value
- of the variable (as opposed to the value that was assigned to the
- variable); case OSUBST: if '?' qualifier, turn off DOBLANK when
- expandined word part; define DOTEMP_ when expanding word part
- of ${..[#%=?]..}; deleted first_eq and tstart - replaced with
- tilde_ok and saw_eq.
-
- * eval.c(expand): tilde expansion: use tstart variable instead of cp;
- changed '?' error message to be like at&t ksh; don't test if strval()
- returns NULL - it doesn't.
-
- * var.c(strval): if !ISSET, instead of returning null, set s to null.
-
- * exec.c(comexec): case TDBRACKET: don't pass DOASNTILDE to evalstr().
-
- * exec.c(scriptexec): changed line[] to buf[] so it doesn't get
- confused with global the line[].
-
- * main.c(initsubs): initialize PS4.
- * edit.c(x_getc): cast char to unsigned before returning.
-
-Mon Sep 26 11:06:55 NDT 1994 Michael Rendell (michael@arlene.cs.mun.ca)
-
- * eval.c(globit): call strnsave instead of strsave; if file has
- trailing /, use stat() to check that it is a directory.
-
- * eval.c(expand): case CSUBST: case #/%: deleted duplicate *dp = 0;
- case CSUBST: case =: copy string and call debunk() to oust MAGICs.
-
- * misc.c(print_value_quoted): deleted bogus shf_shlout argument to
- shprintf(); deleted unneeded test (p != s).
-
- * main.c(main): turn on FBRACEEXPAND.
- * misc.c(change_flag): turn FBRACEEXPAND off if turning FPOSIX on.
-
- * vi.c(x_vi): use x_vi_zotc() to print ^D.
- * vi.c(CHAR_LEN): new define.
- * vi.c(vi_hook): use CHAR_LEN() instead of inline tests for
- c < ' ' || c== 0x7f; search editing: display M- if necessary.
- * vi.c(display): changed to deal tiwh meta-characters.
-
- * vi.c(x_vi_zotc): print M- for meta chars.
- * emacs.c(x_e_getc): new function; changed all x_getc() calls to
- x_e_getc() calls.
- * edit.c(x_getc): don't and out upper bit.
-
- * sh.h(OPAREN,CPAREN,OBRACK,CBRACK,OBRACE,CBRACE): new defines
- * expr.c(OPAREN,CPAREN): re-named to OPEN_PAREN, CLOSE_PAREN.
-
- * eval.c(debunk): changed to convert MAGIC MAGIC -> MAGIC.
- * eval.c(expand): removed ismagic_bracket stuff - not needed.
- * eval.c(expand): always restore value of quote when CSUBST
- reached; don't set DOGLOB in fdo if trimming.
-
-Sat Sep 24 11:46:03 NDT 1994 Michael Rendell (michael@arlene.cs.mun.ca)
-
- * tree.h(DOBRACE_): new define.
- * eval.c(expand): changed check for leading ! in [..] to be more
- robust (old test could have looked before start of string).
- * eval.c(expand,maybe_expand_tilde): case ~: moved code into a function
- (maybe_expand_tilde).
- * eval.c(expand): expand alternations after macros, before globing
- (was before macros).
- * eval.c(alt_expand): changed to be called after macro expansion.
- * eval.c(alt_scan,alt_count): deleted (no longer needed).
-
- * misc.c(cclass): return NULL (no match) if first char in a range
- is greater than the second.
- * eval.c(expand): when building strings, stuff literal MAGIC chars.
-
-Thu Sep 22 15:05:48 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * exec.c(comexec): re-arranged handling of builtin and exec;
- handle command (and command -p, etc.); deleted comexec_flags
- variable; made function static again; removed fcflags argument.
- * table.h(FC_NOBLOCK): deleted define.
- * c_sh.c(c_exec): changed empty function to deal with preserving I/O
- redirects (code taken from comexec()).
- * c_ksh.c(c_command): new function - calls c_whence.
- * c_ksh.c(c_whence): removed code to deal with command -p.
-
- * Makefile.in: changed [ to test.
- * shf.h: changed errno structure member to errno_; changed all uses
- (fixes for QNX from Brian Campbell).
-
- * c_test.c(enum Op): deleted trailing comma (some compilers complain).
- * proto.h: added volatile to tp arg of comexec() prototype.
-
-Thu Sep 22 11:08:31 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * made pdksh-5.0.8 distribution
-
- * Makefile.in(install): added missing dollar (fix from Thomas Gellekum).
-
- * emacs.c: changed CMASK to CHARMASK to avoid conflicts with some
- system headers (eg, HP-UX 9.01 <sys/param.h>). Reported by Sean
- Hogan.
-
- * history.c(c_fc): wp not being incremented; -e strcmp() test reversed
- (reported by Sean Hogan).
-
-Thu Sep 21 21:12:03 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * made pdksh-5.0.7 distribution
-
-Tue Sep 20 09:56:54 NDT 1994 Michael Rendell (michael@arlene.cs.mun.ca)
-
- * history.c(c_fc): use ksh_getopt() to parse arguments.
- * c_ksh.c(c_bind): use ksh_getopt() to parse arguments.
-
- * main.c(initcoms[]): changed hash alias from alias -t - to alias -t --.
-
- * misc.c(print_value_quoted): don't use quotes if no special
- characters.
-
- * c_ksh.c(c_whence): added POSIX command command.
-
- * c_sh.c(c_label): removed check for null wp.
-
- * exec.c(comexec): added new flags argument (FC_*);
- don't call newblock() if FC_NOBLOCK set; pass flags on to
- findcom(); changed all calls; made comexc() a non-static
- function.
-
- * table.h:(FC_SPECBI,FC_FUNC,FC_REGBI,FC_UNREGBI,FC_PATH,FC_DEFPATH,
- FC_NOAUTOLOAD,FC_NOBLOCK): new defines.
- * exec.c(findcom): merged insert/justsearch/autoload arguments
- into one flags argument; changed code to check various flags;
- changed all calls.
-
-Sat Sep 17 20:17:59 NDT 1994 Michael Rendell (michael@garfield.cs.mun.ca)
-
- * exec.c(comexec): print error if builtin has no command.
-
- * exec.c(execute): before doing redirections, check for TCOM and
- evaluate arguments and determine if it is a special builtin;
- print arguments (using PS4) if FXTRACE set; case TCOM: simply call
- comexec().
- * exec.c(comexec): deleted vp argument; only call newblock() if
- needed (ie, !special, !empty); evaluate assignments and put
- in environment one at a time; print environment (using PS4) if
- FXTRACE set; removed code to turn empty command into :;
- removed environment setting code in switch statement.
- * exec.c(echo): deleted function.
-
- * lex.c(yylex): only honour CMDWORD if FPOSIX set.
-
- * c_sh.c(shbuiltins): removed = attribute from false/true commands.
-
- * sh.h(E_TCOM): delete define - not used.
-
- * sh.h(null),var.c: use EXTERN for initialization of null.
- * sh.h(space,newline,slash): new variables (" ", "\n", "/")
- use these everwhere instead of "", " ", "\n", "/".
- * path.c: include sh.h.
-
- * exec.c(execute): combined TFOR/TSELECT cases.
-
-Fri Sep 16 11:32:01 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * lex.h(CMDWORD): new define to prevent continued alias expansion in
- non-command contexts.
- * lex.c(yylex): only set ALIAS if SF_ALIAS and CMDWORD are set.
- * syn.c(get_command): case LWORD/REDIR: pass CMDWORD if argc is 0.
-
- * exec.c(comexec): if there is no command, do assignments and set
- the return value to subst_exstat (used to fake a : command).
-
- * sh.h(subst_exstat): new variable.
- * exec.c(execute): case TCOM: clear subst_exstat before doing eval()s.
- * eval.c(expand): set subst_exstat to return value of waitlast().
- * c_sh.c(c_set): if !FPOSIX, return subst_exstat instead of 0.
-
- * exec.c(execute): removed redundent "exstat = rv;" near if FERREXIT.
- * exec.c(comexec): case CFUNC: for normal function completion, set
- i to 0 and rv to return value of execute() (was i=LRETURN,exstat=..).
-
- * main.c(include): return -1 if file could not be found/opened,
- otherwise, the exit status of the last command is returned;
- changed all calls.
- * c_sh.c(c_dot): print error if include() returns < 0.
-
- * var.c(setspec): ifdef EDIT'd V_VISUAL, V_EDITOR cases.
-
- * misc.c(parse_args): no longer accept set -o alternations as
- a substitute for set -o braceexpand.
-
- * jobs.c(j_exit): when restoring tty process group, also restore
- our process group.
-
- * config.h.bot: define JOB_SIGS iff we have modern signal and wait
- routines.
- * jobs.c: use ifdef JOB_SIGS instead of ifdef JOBS when setting
- signal masks and routines or using waitpid; define TTY_PGRP and
- NEED_PGRP_SYNC seperately from JOBS.
- * jobs.c(j_kill): only send SIGCONT if job is stopped.
- * jobs.c(j_jobs): remove exited/signaled jobs even if !FMONITOR,
- un-ifdef JOBS same.
-
- * jobs.c(check_job): ifdef FNOTIFY with JOBS (noted by
- Michael Haardt <u31b3hs@POOL.Informatik.RWTH-Aachen.DE>).
- * jobs.c(j_notify,j_waitj): put ifdef JOBS around use of FMONITOR.
- * main.c(shell): removed ifdef JOBS from declaration of interactive.
-
- * ksh_limval.h,sh.h: moved include of <limits.h> from ksh_limval.h
- to sh.h since some machines define CLK_TCK there.
-
-Thu Sep 15 09:58:14 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * vi.c(vi_cmd): took out ESC as file completion char in command mode
- (too annoying).
-
- * jobs.c(exchild): if starting a job in the background and FBGNICE
- is set, call nice().
-
- * Makefile.in: changed maxext to manext (fix from Thomas Gellekum
- <thomas@ghpc8.ihf.rwth-aachen.de>); in the install target, check
- if the path of the installed shell is in /etc/shells and
- complain if it isn't; added depend target, removed old $(OBJS)
- and trap.o dependencies.
-
-Wed Sep 14 09:39:55 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * misc.c(options[]): changed position of vi-tabcomplete option.
-
- * lex.c(yylex): ifdef use of FVI/FEMACS/FGMACES with VI/EMACS
- (fix from Gordan Larson <hoh@approve.se>).
-
- * ksh.1(DESCRIPTION): added missing P in \fP
- (fix from Gordan Larson <hoh@approve.se>).
-
-Tue Sep 13 11:01:47 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * made pdksh-5.0.6 distribution
-
-Mon Sep 12 11:39:07 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * exec.c(scriptexec): changed so it will compile if SHARPBANG is
- defined; fixed error message; shell argument is everything up to
- a newline; don't listen to #! line unless it ends in a newline.
-
- * syn.c(get_command): case FOR: changed VARASN to ARRAYVAR.
-
- * jobs.c(waitfor): restore signal mask before returning if named job
- isn't own own; when waiting for unspecified jobs, only consider
- running jobs; don't pass JW_STOPPEDWAIT flag to j_wait.
-
- * table.h(V_TMPDIR,tmpdir): new define/variable.
- * var.c(setspec, unsetspec): added case for V_TMPDIR.
- * io.c(maketemp): use tmpdir variable if it is set, else use /tmp.
-
- * var.c(popblock): if poping a variable that wasn't set in the old
- environment, call unsetspec().
-
-Fri Sep 9 10:37:18 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * sh.h(PATHMAX): increased value from 256 to 1024.
-
- * main.c(main): moved initialization of name to start of main;
- if getcwd() fails, use name in error message and call shf_flush().
-
- * io.c(maketemp): check/use TMPDIR variable instead of /tmp; allocate
- temp structure and path in one chunk.
-
- * c_ksh.c(c_cd): when checking for no home directory, compare
- against null, not (char *) 0.
-
-Thu Sep 8 10:52:59 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * lex.c(yylex): case SHIST: flush shl_out after printing command.
-
- * jobs.c(check_job): when notifing, do not remove job if it is stopped.
-
-Wed Sep 7 10:55:35 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * made pdksh-5.0.5 distribution
-
- * main.c(shell): commented out shf_flush(shl_out) - shouldn't be
- needed since -v flushes itself.
-
-Tue Sep 6 09:30:57 NDT 1994 Michael Rendell (michael@arlene.cs.mun.ca)
-
- * sh.h(LSHELL,really_exit): new define/variable.
- * c_sh.c(c_exitreturn): if how is LEXIT, check if there are stopped
- jobs and, if so, unwind with LSHELL (also check/set really_exit).
- * main.c(shell): added case for LSHELL - stop unwinding if shell
- is interactive; changed local reallyquit to global really_exit.
- * main.c(include),exec.c(comexec): added case for LSHELL.
-
- * c_sh.c(c_exitreturn): quitenv() for LRETURN as well as LEXIT.
-
- * sh.h(TF_CHANGED): new define.
- * trap.c(runtrap): default EXIT/ERR trap during execution and restore
- original if TF_CHANGED not set.
- * trap.c(settrap): set TF_CHANGED when setting trap.
-
- * jobs.c(j_stopped): check that job created by current process; print
- "You have stopped jobs" message.
- * main.c(shell): don't print you have stopped jobs message.
-
- * main.c(initcoms): removed echo alias.
- * c_ksh.c(kshbuiltins): added echo as a builtin.
- * c_ksh.c(c_print): if wp[0] is echo, act like strict sysv echo;
- added \a (BEL) escape sequence.
-
- * syn.c(function_body): new function; calls get_command() to get
- the body of a function (old code did nested { } block which
- caused problems with how redirections after the block were
- handled).
- * syn.c(get_command): call function body to deal with foo() and
- function foo.
-
- * jobs.c(restore_ttypgrp): new variable.
- * jobs.c(j_change): set restore_ttypgrp if process group is set.
- * jobs.c(j_exit): if necessary, restore tty process group for main
- shell.
-
-Fri Sep 2 21:32:03 NDT 1994 Michael Rendell (michael@arlene.cs.mun.ca)
-
- * main.c(main): set FPRIVILEGED if uid (gid) doesn't match euid (egid);
- don't include $HOME/.profile if FPRIVILEGED; include
- /etc/suid_profile instead of $ENV if FPRIVILEGED.
- * misc.c(change_flag): if clearing FPRIVILEGED flag, set euid (egid)
- to uid (gid).
-
-Fri Sep 2 21:10:23 NDT 1994 Michael Rendell (michael@arlene.cs.mun.ca)
-
- * main.c(main): don't include $ENV if uid (gid) doesn't match
- euid (egid) (from J.T.Conklin).
-
-Fri Sep 2 12:07:14 NDT 1994 Michael Rendell (michael@arlene.cs.mun.ca)
-
- * syn.c(get_command): removed MPAREN case, taken care of in '(' case,
- as per POSIX.2 which says () is two operators, not one.
- * lex.c(yylex): don't check for/return MPAREN.
- * lex.h(MPAREN): deleted define.
-
- * configure.in: add test for library routine confstr(); add
- header test for paths.h.
- * sh.h: include paths.h if available; define DEFAULT__PATH.
- * table.h(def_path): new variable.
- * options.h(DEFAULT_PATH): new define.
- * main.c(main): initialize value of def_path; set path to def_path;
- remove PATH initalization from initsubs; do not set value of HOME
- variable (POSIX); allow SHELL, PS1, PS2, PS3 to have empty values
- (at&t ksh).
- * var.c(unsetspec): when unsetting PATH, set path to def_path.
-
- * jobs.c(j_waitj): restore proc mask before calling error if
- 1st tcsetpgrp() fails.
-
-Thu Sep 1 10:28:03 NDT 1994 Michael Rendell (michael@arlene.cs.mun.ca)
-
- * Makefile.in: added check-sig.c, check-fd.c and check-pgrp.c
- to RCSFILES; added rules for compiling the above; added debugtools
- target to compile them all.
-
- * c_test.c(arg0,t_error,T_ERR_EXIT): new variables/defines.
- * c_test.c(c_test): set arg0 to wp[0], t_error to 0; after
- calling eval_binop() or oexpr() check t_error and if set,
- return T_ERR_EXIT.
- * c_test.c(syntax): set t_error exit; use shellf() instead of
- errorf(); use arg0 instead of "test"; delete GCC_FA_NORETURN
- attribute; changed all calls to return after calling.
- * c_test.c(oexpr,aexpr,primary): check terror after calling
- oexpr(), aexpr(), nexpr().
-
- * c_test.c(primary): if unary operator is -t and there is no
- argument, don't increment t_wp; if missing closing parenthesis,
- show next operand (if any) in error message.
- * c_test.c(eval_unop): default case, print t_wp[-2] (was -1).
- * c_test.c(c_test): set t_wp before calling eval_binop() incase
- there is an erorr.
- * c_test.c(syntax): print first message even if op is an empty string.
-
-Wed Aug 31 11:48:51 NDT 1994 Michael Rendell (michael@arlene.cs.mun.ca)
-
- * expr.c(O_LT, O_GT): reverse order of enums to match opinfo table.
-
- * c_test.c(nexpr): always call !nexpr() (never !primary()).
- * c_test.c(c_test): switch on argc-1 to make code match POSIX
- description; make 4 arg case fall into 3 arg case, and 3 arg case
- fall into 2 arg case.
- * c_test.c(is_not,is_and,is_or): new defines.
- * c_test.c(c_test,oexpr,aexpr,nexpr): use is_not,is_and and is_or.
- * c_test.c(primary): don't decrement t_wp in final string case.
-
- * c_test.c(eval_unop): change S_ISIFO to S_ISFIFO and S_ISFITO
- to S_ISFIFO.
-
- * misc.c(parse_args): use OF_SET when initializing set_opts.
-
-Wed Aug 31 09:32:39 NDT 1994 Michael Rendell (michael@arlene.cs.mun.ca)
-
- * made pdksh-5.0.4 distribution
-
- * jobs.c(j_change): do not restore tty process group when turning
- off job control; no need to save original tty process group;
- deleted orig_ttypgrp variable. (fixes bug in which turning off
- job control causes an interactive shell to exit)
-
-Tue Aug 30 14:43:48 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * aclocal.m4(KSH_OPENDIR_CHECK): always include sys/types.h;
- set return value according to what failed.
-
-Tue Aug 30 11:17:09 NDT 1994 Michael Rendell (michael@arlene.cs.mun.ca)
-
- * missing.c(strerror): for systems without sys_errlist[], report
- error number if unknown.
-
- * Makefile.in: added BUG-REPORTS to DISTFILES.
-
- * jobs.c(exchild): do tcsetpgrp() in both parent and child after
- the first process is created (may need to change to every child).
-
- * aclocal.m4(KSH_PGRP_SYNC): new test - defines NEED_PGRP_SYNC.
- * acconfig.h: added define for NEED_PGRP_SYNC.
- * configure.in: use KSH_PGRP_SYNC test.
- * jobs.c(exchild,j_startjob,j_sync_open,j_sync_pipe): if NEED_PGRP_SYNC
- is defined, use a pipe to block the first process in a pipeline
- until the whole pipeline is set up.
-
-Mon Aug 29 09:15:00 NDT 1994 Michael Rendell (michael@arlene.cs.mun.ca)
-
- * jobs.c(exchild): for background, unmonitored jobs, don't open
- /dev/null if input is a pipe.
-
- * jobs.c(exchild): for background, unmonitored jobs, use setsig()
- instead of setexecsig() to set up SIGQUIT and SIGINT; changed
- restoration of SIGTSTP,SIGTTIN,SIGTTOU - set them to DFL if
- monitoring and not a `..` command, otherwise leave them alone.
- * jobs.c(j_init): only use SIGTSTP,SIGTTIN,SIGTTOU if talking
- or monitoring - if just talking leave signals ignored.
- * jobs.c(j_change): if going into job control, set TF_SHELL_USES
- flag for sigtraps[SIGTSTP,SIGTTIN,SIGTTOU]; if leaving job control
- ignore signals if interactive, else restore original signals.
-
- * table.h(SPEC_BI, REG_BI): new defines.
- * exec.c(builtin): check for * or + in front of builtin names and set
- SPEC_BI or REG_BI if found.
- * exec.c(findcom): search for special builtins first, then functions,
- then regular builtins, then PATH search.
- * c_sh.c(shbuiltins[]),c_ksh(kshbuiltins[]): add */+ in front of POSIX
- special/regular builtins; add = infront of unset;
- remove = from alias.
- * c_sh.c(c_label): set exit value according to name (for true/false).
- * c_sh.c(shbuiltins[]): add entries for true and false.
- * main.c(initcoms[]): deleted true/false aliases.
-
- * aclocal.m4(KSH_OPENDIR_CHECK): new test - see if opendir() will
- open non-directories.
- * configure.in,acconfig.h: added KSH_OPENDIR_CHECK.
- * missing.c,ksh_dir.h(ksh_opendir): new define/function.
- * eval.c(globit),emacs.c(compl_file): use ksh_opendir() instead of
- opendir().
-
- * main.c(include): save source filename since search() uses line[]
- for the filename and shell() trashes line[].
-
- * table.h(FINUSE,FDELETE) new defines.
- * exec.c(execute): case CFUNC: re-arranged code so normal return goes
- through setjmp() switch; use FDELETE/FINUSE flags to avoid problems
- with a function being undefined or redefined during its execution.
- * exec.c(define): if FINUSE is set, set FDELETED and find a new table
- entry.
-
-Fri Aug 26 21:58:25 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * lex.c(getsc_): flush output after write when echoing.
-
- * Makefile.in(dist): after creating distrubution, use pathchk -p
- to check file names.
-
-Fri Aug 26 10:28:20 NDT 1994 Michael Rendell (michael@arlene.cs.mun.ca)
-
- * made pdksh-5.0.3 distribution
-
- * expr.c(IS_ASSIGNOP): new define.
- * expr.c(evalexpr): use IS_ASSIGNOP (bug fix).
-
- * exec.c(execute): case TFOR,TSELECT: change e->type just
- before setjmp() to avoid problems with bad jmpbufs.
-
- * jobs.c(startlast): new function.
- * jobs.c(waitlast): print error if job not started.
- * eval.c(comsub): call startlast() after execute().
- * jobs.c(exchild,j_startjob,j_sync_pipe): when starting a pipeline
- use a pipe to ensure the first process doesn't die before
- the last process is started.
-
- * exec.c(execute): case TFUNC: set/clear FXTRACE according to
- tp->flag & TRACE, and restore old value when function completes.
-
- * c_test.c,exec.c,io.c,mail.c,vi.c: changed all uses of
- (x&S_IFMT) == S_IF* to the equivilent S_IS* (for ISC unix).
- * c_test.c(eval_unop): if system doesn't have symlinks or sockets
- (S_ISLNK,S_ISSOCK), return 0 (used to cause internal error).
- * ksh_stat.h(S_ISVTX): define if sys/stat.h doesn't.
-
- * sigaction.c(Signal,signal): ifdef'd Signal() and signal() out as
- they cause header file conflicts on some systems (eg, signal()
- in ISC unix); also ifdef'd out other routines not used by ksh
- (ie, sigdelset, sigfillset, sigismember, sigpending).
-
-Thu Aug 25 11:50:03 NDT 1994 Michael Rendell (michael@arlene.cs.mun.ca)
-
- * c_test.c(primary): always check that *t_wp isn't 0 before using it.
-
- * eval.c(homedir): cache home directory values.
-
- * exec.c(findcom): search builtins before tracked aliases.
-
- * table.h(commands,taliases): changed name of commands to taliases.
-
- * c_ksh.c(c_unalias): changed to use ksh_getopt(); added -t and -a
- options; exit with non-zero value if non-alias name unaliased
- (POSIX).
-
- * main.c(initcoms[]): alias hash to 'alias -t -'; added autoload alias
- as well; set selected comands to be tracked aliases (eg, grep,
- ls, who, vi, emacs, etc.).
-
- * c_ksh.c(c_alias): when printing aliases, check ISSET, not DEFINED
- flag (so unset tracked aliases won't cause problems); changed
- to use ksh_getopt(); added -t flag; added -x flag (does nothing).
- * c_ksh.c(c_hash): deleted function; removed all references.
-
- * table.h(CTALIAS): new define.
- * exec.c(findcom): added search argument for whence -p; fixed
- introduced bug preventing tracking of commands when insert set;
- changed all calls; when creating tracked aliases, set type to CTALIAS
- (was CEXEC).
- * exec.c(findcom,flushcom): when freeing old tracked aliases, use
- APERM, not commands.areap.
- * c_ksh.c(c_whence): changed to use ksh_getopt(); assume findcom()
- never returns 0 and never returns tp->type == CNONE; made output
- closer to at&t ksh output; combined vflag/!vflag switch statements;
- added case for CTALIAS.
- * exec.c(findcom): set tracked alias type to CTALIAS.
-
- * c_ksh.c(c_print): added -s option; changed to use Xstring() routines
- and write() instead of shf routines; returns non-zero if there
- was a write error.
-
- * jobs.c(struct job): changed pid_t lpid field to Proc *last_proc;
- changed all uses.
- * jobs.c(check_job): use j->last_proc instead of lp.
- * jobs.c(j_waitj): when checking for fake ^C, test j->last_proc
- status to see if it was signaled and use WTERMSIG to get signal.
-
- * main.c: initialize integer TMOUT parameter to 0; call alarm_init()
- if FTALKING.
- * trap.c(alarm_init,alarm_catcher): new functions.
- * trap.c(runtraps): if ksh_tmout_leave is set, exit.
- * sh.h(TMOUT_EXECUTING,TMOUT_READING,TMOUT_LEAVING,ksh_tmout,
- ksh_tmout_state): new enum values/variables.
- * table.h(V_TMOUT): new define.
- * var.c(special,setspec,unsetspec): added V_TMOUT entry.
- * edit.c(x_getc): call intrcheck() if read interrupted.
-
-Thu Aug 25 09:36:54 NDT 1994 Michael Rendell (michael@arlene.cs.mun.ca)
-
- * c_test.c(c_test): for argc cases 4 and 5, return the complement
- of the expressioin result; for [[ .. ]] expressions, don't parse
- based on argc; deleted struct t_op.op_flags field and related
- defines UNOP,BINOP,ACCEPT_BE,ISTEST,ISDBRACKET,ISBOTH - changed all
- uses to test the value of isdbracket.
- * c_test.c(filstat): moved body of filstat() into eval_unop(), deleted
- filstat().
-
- * c_test.c: incorperated changes from J.T. Conlin (jtc@cygnus.com)
- for POSIXization of test builtin.
-
-Wed Aug 24 12:16:25 NDT 1994 Michael Rendell (michael@arlene.cs.mun.ca)
-
- * new-version.sh: new file - updates date in version.c
- * Makefile.in: added new-version.sh to RCSFILES; call new-version.sh
- in dist: target.
-
-Tue Aug 23 09:28:10 NDT 1994 Michael Rendell (michael@arlene.cs.mun.ca)
-
- * made pdksh-5.0.2 distribution
-
- * jobs.c(exchild): don't call restoresigs().
- * exec.c(execute): do call restoresigs() (just before execve()).
-
- * c_sh.c(c_trap): ifdef'd out code to print default traps. Too ugly
- and it isn't clear POSIX needs it.
-
- * c_ksh.c(c_print): put -e option back in for echo emulation (-R).
-
- * c_sh.c(c_shift): generate error if n < 0.
-
- * c_sh.c(c_trap): use shellf instead of errorf to report errors
- (so we can return a value instead of unwinding - POSIX).
-
- * exec.c(execute): if command fails and !FERREXIT, call
- trapsig(SIGERR_).
-
- * c_sh.c(c_exit,c_return,c_exitreturn): combined c_exit and c_return
- functions.
-
-Mon Aug 22 09:39:54 NDT 1994 Michael Rendell (michael@arlene.cs.mun.ca)
-
- * eval.c(expand): case XARG: set word to IFS_WORD to force null
- words to be created.
-
- * lex.c(yylex): added indquotes flag and code for `...` parsing
- (to deal with "`...`" the way sh/at&t-ksh does).
-
- * trap.c(runtrap): don't reset ERR trap.
-
- * sh.h: combnied SS_USER/SS_FORCE flags with RESTORE_CURR et. al.
- flags; changed RESTORE_* to SS_RESTORE_*.
- * trap.c(setsig): combined restore, force and user flags; changed
- all calls.
- * trap.c(setexecsig): use SS_RESTORE_* values as argument.
-
- * table.h: changed LCASE to LCASEV (and UCASE_AL to UCASEV_AL) to
- avoid problems with ioctl/tty LCASE define.
-
- * sh.h(struct env): deleted interactive field.
- * main.c(shell),exec.c(iopsetup): deleted e->interactive assignment.
-
- * sh.h: made e a struct env * (was struct env); changed all references.
- * main.c(newenv): copy loc, flags and interactive fields explicitly.
-
- * var.c(newblock): allocate block structure, don't assume already
- exists.
- * var.c(popblock): free old block structure.
- * main.c(main): set e->loc to 0 before calling newblock().
- * exec.c(comexec): let newblock() allocate new structure; deleted
- l variable (changed references to e->loc).
- * table.h: deleted globals variable.
-
- * c_ksh.c(c_print): treat a lone - like --.
-
- * main.c(main),trap.c(inittraps): move SIGINT,SIGQUIT,SIGTERM signal
- initialization to inittraps() and do it regardless of FTALKING.
-
- * trap.c(settrap): deleted force trap since probably will never
- add -f flag to trap.
-
- * main.c(unwind): if we are dieing of SIGINT or SIGTERM, kill
- ourselves with a signal.
-
- * vi.c(x_vi),emacs(x_emacs): if ^C read, call trapsig()/runtraps();
- don't return -2.
- * edit.c(x_read): don't check for -2 return value.
- * vi.c(x_vi): check for quit char (^\) and fake SIGQUIT.
-
- * exec.c(comexec): made flags argument volatile.
-
- * misc.c(getn_): new function.
- * c_sh.c(c_exit,c_return): call quitenv() before unwind()ing;
- moved c_exit() next to c_return(); use getn_() instead of getn().
-
- * main.c(shell): added exit_atend argument to deal with POSIX trap exit
- semantics; changed all calls.
- * sh.h: added STOP_RETURN macro.
- * c_sh.c(c_return): determine if we are returning or exiting before
- unwind()ing so POSIX trap exit semantics are honored.
-
- * jobs.c(j_sigchld): call trapsig() instead of messing with sigtraps[].
- * trap.c(trapsig): don't restore signal handler if it wasn't set to
- trapsig.
-
- * sh.h: added TF_TTY_INTR flag.
- * trap.c(inittrap): set TF_TTY_INTR for SIGINT.
- * jobs.c(j_waitj): if
-
- * jobs.c,sh.h: deleted SA_RESTART ifdefs; moved SIGCLD->SIGCHLD ifdefs
- from jobs.c to sh.h.
-
-Sat Aug 20 15:26:24 NDT 1994 Michael Rendell (michael@arlene.cs.mun.ca)
-
- * sh.h: added KSH_SA_FLAGS define.
- * trap.c(inittrap,setsig): set sa_flags field to KSH_SA_FLAGS.
- * sigact.c(sigaction): if using BSD42_SIGNALS, set the SV_INTERRUPT
- flag.
- * configure.in: deleted AC_RESTARTABLE_SYSCALLS.
- * config.h.bot: add error message to prevent compilation if using
- BSD41 signals.
-
- * shf.h: added SHF_INTERRUPT flag.
- * shf.c(shf_fillbuf,shf_putchar,shf_write,shf_emptybuf): call
- intrcheck() if read()/write() interrupted and SHF_INTERRUPT set.
- * c_sh.c(c_read): use SHF_INTERRUPT flag.
- * lex.c(getsc_): call intrcheck() if read() interrupted.
-
- * main.c(main),trap.c(inittrap): moved Sigact* initialization
- from main() to inittrap(); made Sigact_trap/Sigact_ign static;
- deleted Sigact and Sigact_dfl.
- * sh.h: deleted declarations of Sigact*.
-
- * main.c(shell): deleted sigaction call - no longer needed.
-
- * sh.h: added RESTORE_CURR, RESTORE_ORIG, RESTORE_DFL and RESTORE_IGN
- defines.
-
- * trap.c(intrcheck): new function.
- * trap.c(runtraps): added intr argument; clear trap/intrsig
- before running traps; changed all calls.
- * trap.c(runtrap): save/restore exstat when running trap.
- * jobs.c(j_waitj): changed interrupt test to check intrsig
- and return -1.
- * jobs.c(waitfor): if j_waitj() returns -1, call intrcheck().
- * jobs.c(j_change): use setsig() instead of sigaction() to
- set up SIGTTIN,SIGTTOU,SIGTSTP.
-
- * trap.c(inittraps): initialize flags for INT/QUIT/TERM.
- * sh.h(intrsig): new variable.
- * trap.c(trapsig): set intrsig if signal has TF_DFL_INTR flag set;
- deleted longjmp().
- * trap.c(runtraps): clear intrsig.
- * trap.c(runtrap): if signal is defaulted and TF_DFL_INTR is
- set, set exstat and call unwind(); return if signal ignored;
- reset an ERR trap before executing it.
- * trap.c(cleartraps): deleted special case for EXIT; reset
- command traps using settrap(); clear intrsig.
- * trap.c(restoresigs): only deal with traps that have the TF_EXEC_IGN
- flag set (others take care of themselves).
-
- * trap.c(sigtraps[]): added ERR trap.
- * trap.c(gettrap): deleted #if 0'd ERR/EXIT check.
- * trap.c(gettrap,runtrap,cleartraps,restoresigs): use SIGNAL+1 to
- go through trap table.
- * sh.h(SIGEXIT_,SIGERR_): new defines.
- * c_kill.c(c_kill): test for signals > 128 (was >= 128)
- * c_sh.c(c_trap): when printing traps, use SIGNALS+1.
-
- * sh.h(struct trap): replaced ourtrap and sig_dfl fields with
- flags field; defined TF_SHELL_USES, etc. for flags field; added
- cursig field.
- * sh.h(struct env): replaced func_parse field with
- flags field; defined EF_FUNC_PARSE, EF_BRKCONT_PASS for flags
- field; defined STOP_BRKCONT(); changed uses of func_parse
- (get_command()/readhere()).
- * c_sh.c(c_brkcont): use STOP_BRKCONT(), EF_BRKCONT_PASS; call
- unwind() to do the work.
-
-Fri Aug 19 09:59:43 NDT 1994 Michael Rendell (michael@arlene.cs.mun.ca)
-
- * trap.c(settrap): new function - does most of what c_trap did.
- * c_sh.c(c_trap): changed to use settrap(); print out default
- actions as well as caught/ignored actions.
- * trap.c,c_sh.c(setsig): moved setsig from c_sh.c to trap.c and
- made it static; added force and user arguments; don't do anything
- for EXIT and ERR.
- * main.c(main): use sigtrap() instead of ignoresig().
- * trap.c(ignoresig): deleted function.
-
- * exec.c(execute): case TSELECT: don't change SIGINT signal handler.
-
- * proto.h: use GCC_FA_NORETURN on aerror().
- * syn.c(yyparse): made function static and void.
-
- * exec.c(herein): changed error() calls to errorf()s; use error()
- in error handler; call shf_close() instead of shf_fdclose().
-
- * tree.h,sh.h: moved LBREAK/LCONTIN from tree.h to sh.h;
- added LEXIT, LRETURN, LERROR, and LINTR defines; changed values
- of LBREAK/LCONTIN; changed all calls to longjmp() and setjmp().
- * exec.c(execute): put Break: label after main switch, changed
- goto Break[0-9] to Break; deleted Break[0-9] labels.
- * exec.c(execute): changed FOR, SELECT, WHILE, DO loop setjmps
- to explicitly check for LBREAK/LCONTIN, otherwise call unwind().
- * exec.c(execute): case TFUNC: added setjmp switch statement to take
- care of various L* values.
- * main.c(include,shell): added setjmp switch statement to take care of
- various L* values.
- * main.c(unwind): added L* parameter to pass on to longjmp();
- changed all calls.
- * c_sh.c(c_return): just call unwind(LRETURN);
- * main.c(unwind): put code from leave() in E_NONE case.
- * main.c(error,leave): deleted functions; replace all calls with
- unwind(LLEAVE or LERROR).
- * *.c(longjmp): replaced all calls with unwind(L..) (except the
- call in unwind()).
-
- * shf.h: add areap field to struct shf.
- * shf.c(shf_fdopen,shf_sopen): initialize areap
- * shf.c(shf_emptybuf,shf_close,shf_sclose,shf_finish): use areap
- instead of ATEMP.
-
- * shf.c(shf_sopen): if buf is 0 and writing and DYNMAIC, allocate
- a buffer; if writing, save room for a trailing null.
- * shf.c(shf_sclose): new function.
- * shf.c(shf_snprintf),tree.c(snptreef): use shf_sclose().
- * tree.c(snptreef): changed return type to char *; if buffer
- is null, pass SHF_DYNAMIC to shf_sopen(); return (possibly
- allocated) string.
- * syn.c(syntaxerr): use snptreef() instead of ident.
-
- * tree.h: new define TDBRACKET; new defines DB_NORM,DB_OR,DB_AND,
- DB_BE,DB_PAT.
- * tree.c(ptree): added case for TDBRACKET.
- * syn.c(get_command): case DBRACKET: make TDBRACKET command;
- at end of function, null terminate args/vars if TDBRACKET.
- * c_test.c(is_db_patop): new function.
- * syn.c(db_primary): set type of arg to DB_PAT if is_db_patop()
- returns true.
- * exec.c(execute): added case for TDBRACKET.
-
- * syn.c(get_command): case MDPAREN: make arg[0] an allocated stuffed
- string (was a literal string).
-
-Thu Aug 18 11:06:49 NDT 1994 Michael Rendell (michael@arlene.cs.mun.ca)
-
- * c_test.c(is_op,is_binop,is_unop): new functions to test for
- unary/binary operators.
- * c_test.c(oexpr,aexpr,nexpr,primary): no longer take argument -
- call is_unop/is_binop directly.
- * c_test.c(ISDBRACKET,ISTEST,ISBOTH,ACCEPT_BE): new defines.
- * c_test.c(struct t_op): changed op_type field to op_flags.
- * c_test.c(ops[]): broke into two arrays: u_ops and b_ops;
- set flag field to ISDBRACKET/ISTEST/ISBOTH as appropriate.
- * c_test.c(t_lex): deleted function.
- * c_test.c(primary): before checking for unary operator, check
- for -BE (binary expression next) if appropriate.
-
- * c_test.c: made operator type an enum to make it easier to add
- operators; changed oexpr/aexpr/nexpr/primary/filstat/t_lex
- operand/return types.
- * c_test.c(struct t_op): changed op_text from char * to char [4].
- * c_test.c(primary): case FILTT: using digit(**t_wp) causes core dump
- when there is no arg - just test if *t_wp is 0; move test into
- filstat().
- * c_test.c(primary): use *opnd1 != 0 instead of strlen(opnd1) (3
- instances).
-
- * tree.c(wdscan,wdcopy): changed string argument to const; changed
- return type of wdscan to const.
-
- * eval.c(expand): case CSUBST: case '?': use st->var->anme instead
- of cp to allow proper nesting.
- * eval.c(expand): case OSUBST: don't change cp - declare local
- variable.
- * eval.c(expand): case COMSUB: deleted Xsavepos() call; XCOM: deleted
- Xrestpos() call.
- * eval.c(expand): save the position of the first unquoted = for tilde
- expansion.
- * eval.c(expand): case '~': use sp == (cp+2) instead of dp == Xstring
- so we aren't fooled by ''~ or ${foo}~; sp[-1]/sp[-2] and firsteq
- for the DOASNTILDE after first = or unquoted : test.
-
- * tree.h(struct op): changed noexpand field to evalflags; changed
- all uses.
- * exec.c(execute): if t->evalflags is non-zero, pass them to eval().
-
- * lex.h: added DBRACKET define for [[ keyword.
- * syn.c(get_command): added case for DBRACKET.
- * syn.c(db_parse,db_oaexpr,db_nexpr,db_primary): new functions
- to parse [[ .. ]] expressions.
- * syn.c(tokentab[]): added [[/DBRACKET keyword.
- * c_test.c(is_db_unop,is_db_binop): new functions to test if arg
- is [[ .. ]] unary/binary operator.
-
- * syn.c(syntaxerr): call REJECT; before token; removed REJECT
- before all calls to syntaxerr().
- * syn.c(get_command): removed syntax error kludge.
-
-Wed Aug 17 11:07:40 NDT 1994 Michael Rendell (michael@arlene.cs.mun.ca)
-
- * c_test.c(struct ops): changed -U to -O.
-
- * tree.h: added new defined DOASNTILDE.
- * eval.c(expand): case '~': changed !(f&DOBLANK) to f&DOASNTILDE.
- * exec.c(execute): case TCOM: pass DOASNTILDE when evaluating vars
- and when expanding args when t->noexpand is set.
-
- * exec.c(execute): case TCASE: pass DOTILDE to both evalstr() calls
- (POSIX).
-
- * syn.c(get_command): don't check for redirections before determining
- command type; handle REDIR where LWORD are handled; default case
- always returns; pass ARRAYVAR flag to tpeek() if t->noexpand;
- don't allow redirections before "x()" function; don't allow
- redirection before keywords; allow a '(' in the case LWORD/REDIR:
- if no variables or arguments (POSIX doesn't allow this, but
- at&t ksh/bourne sh do).
- * lex.h(ARRAYVAR): new define.
- * lex.c(yylex): parse x[1 & 2] as one word if VARASN|ARRAYVAR.
-
- * var.c(is_wdvarname): added aok argument; changed all calls.
- * syn.c(get_command): case FOR/SELECT: check identifier is valid.
-
- * c_sh.c(c_trap): use print_value_quoted() to print traps;
- use ksh_getopt() to skip possible --.
- * trap.c(gettrap): allow digits only if signal numbers match
- POSIX values (ie, HUP=1,INT=2,QUIT=3,ABRT=6,KILL=9,ALRM=14,TERM=15).
-
- * misc.c(print_value_quoted): new function to print strings with
- appropriate quoting.
- * c_ksh.c(c_typeset,c_alias): use print_value_quoted() when printing
- values.
-
- * lex.h: added new ESACONLY flag - only accept ESAC keyword.
- * lex.c(yylex): check for ESACONLY flag when doing keyword search.
- * syn.c(caselist): pass ESACONLY flag to tpeek().
-
-Tue Aug 16 10:17:47 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * lex.h(struct source); changed echo field to generic flags field;
- defined SF_ECHO and SF_ALIASEND.
- * lex.c(_getsc): case SALIAS: use isspace() to check for trailing
- space in alias; if alias does not end in a space, return a fake
- space to keep the current alias in the source list - this allows
- recursive alias detection; set SF_ALIAS in next source if alias
- does end if space.
- * lex.c(yylex): deleted expanding_alias, rec_alias_cnt and
- rec_alias_table variables; check for recursive aliases by checking
- the source list; don't use EXPALIAS flag; if SF_ALIAS is set in
- current source, set ALIAS flag and clear SF_ALAIS; deleted global
- alias variable.
- * table.h: deleted EXPALIAS define.
- * main.c(shell): changed s->echo to set/clr of SF_ECHO in s->flags.
-
- * table.h: added aliases and keywords tables; deleted lexicals table
- (POSIX says they are seperate).
- * syn.c(keywords,initkeywords): changed name of keywords() function
- to initkeywords(); changed all calls; add to keywords table instead
- of lexicals table.
- * main.c(main): initialized aliases/keywords tables; deleted
- initialization of lexicals table.
- * c_ksh.c(c_whence,c_alias,c_unalias),lex.c(yylex): use
- keywords/aliases tables instead of lexicals table; removed unneeded
- type == CALIAS checks.
-
- * var.c(getint): new function, largely take from strint().
- * var.c(strint): call getint() to do most of the work; if vq
- was an allocated string, free the string and clear the alloc
- flag.
- * var.c(intval): call getint() instead of strint().
-
- * mail.c(mcheck): use getint() instead of strint() when getting
- value of MAILCHECK.
-
- * var.c(skip_varname): added argument to allow array references;
- changed all calls.
- * var.c(set_array): remove valid variable name check - done in
- parse_args().
-
- * var.c(strint): check if getspec()/setspec() need to be called.
- * var.c(intval): remove getspec()/INTEGER checks - let strint() do it.
-
- * var.c(skip_wdvarname,is_wdvarname,is_wdvarassign): new
- functions.
- * lex.h(VARASN): new define indicating variable assignment expected,
- currently used to parse "x[1 & 2]" as one token - may be used
- in future in returning AWORD (assignment word) to the parser.
- * lex.c(yylex): Subst: case '[': use is_wdvarname() in determining
- whether to parse an array dereference; do not require an = after the
- dereference (typeset -r x[1 & 2] is legal).
- * syn.c(many functions): pass VARASN to token/musthave/tpeek/synio
- when ever the next token might be the first word of a simple
- command.
- * syn.c(get_command): case LWORD: use is_wdvarassign() to distinguish
- variable assignments from normal arguments; allow aliases after
- redirections and variable assignments; generate syntax error
- for "foo=bar bogusfunction()"; allow array variables in for
- and select statements.
- * lex.c: make global alias variable static (no longer used by
- get_command()).
-
- * syn.c(get_command): put MDPAREN into its own case.
-
- * lex.c(yylex): deleted place holder for tilde expansion.
-
- * tree.h(struct tree): added noexpand field for
- alias/export/readonly/typeset.
- * syn.c(newtp),tree.c(tcopy): initialize/copy noexpand field.
- * syn.c(get_command): case LWORD: set noexpand if assign_command()
- returns true.
- * syn.c(assign_command): new function - returns true if command
- is alias, export, readonly or typeset.
- * exec.c(execute): case TCOM: don't pass DOTILDE flag when
- expanding t->vars; don't do field splitting/globbing/tilde expansion
- of t->args if t->noexpand is set.
-
- * table.h: re-grouped the struct tbl flags into common, variable,
- funtion, builtin/alias, etc (some values overlap); new flag
- names: KEEPASN (was overloaded with TRACE) and NOEXPAND.
- * exec.c(comexec,builtin): changed TRACE to KEEPASN.
-
- * tree.c(tcopy): when copying t->str, use strsave(), not wdcopy()
- if not copying a TCASE.
-
- * c_ksh.c(c_typeset): added -p flag for POSIX export/readonly.
-
- * eval.c(expand): expand tilde in place; don't do tilde expansion
- on results of substitution (POSIX); only do tilde expansion
- if login name is unquoted (POSIX); don't check for fdo&DOTILDE
- when a word is completed.
- * eval.c(tilde): changed to return home directory of a given login name
- (taking care of null/+/-) (old version copied string, scanning
- for, and replacing, magic tildes).
-
- * exec.c(findcom): don't create commands table entries when
- not inserting; when doing access test of tracked alias,
- check for ISSET, not ALLOC (but test ALLOC before calling afree).
- * exec.c(search): use strcpy() instead of loop.
-
-Mon Aug 15 14:46:58 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * c_ksh.c(c_print): added at&t ksh -R flag; deleted -e flag;
- changed to use ksh_getopt().
- * main.c(initcoms[]): changed echo alias from 'print -' to 'print -R'.
-
- * sh.h: new variable procpid; added pid field to struct temp.
- * jobs.c: changed references to my_pid to procpid; deleted my_pid
- variable.
- * io.c(maketemp): initialize pid field from procpid.
- * main.c(remove_temps): only remove temporary files created by
- the current process.
-
-Sun Aug 14 11:47:05 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * var.c: added var field to struct Expand and struct SubType; deleted
- struct SubType.name field.
- * var.c(expand): case OSUBST: use x.var/st->var field to save result
- of global() for use in case CSUBST - this avoids problems with
- x[i+=1] being evaluated twice; check to see if value is being
- assigned to non-variable (eg, ${*:=aja}) or read-only variable.
- * var.c(varsub): set value of xp->var; possibly generate error if
- FNOUNSET set when expanding ${#*}, ${#var}, or ${#array[*]}.
-
- * table.h: added struct tbl.areap field to get rid of lastarea
- problems; deleted lastarea variable; changted all refernces
- to lastarea to var->areap.
- * table.c(tenter): initialize areap field.
- * var.c(arraysearch): deleted area parameter; initialize areap field.
- * var.c(global,local,intval,setint): initialize areap field of vtemp.
-
-Fri Aug 12 10:54:51 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * expr.c: re-wrote e*() functions using single function and table;
- token() now does table lookup; added full C expressions (sans
- pre/post increment, sizeof).
-
- * table.h(INT_U,INT_L): new flags.
- * var.c(strval): handle INT_U.
- * c_ksh.c(c_typeset): add exclusions for INT_U/INT_L;
- add -U option for unsigned (non-at&t ksh).
-
- * var.c(set_array): use global() instead of local();
-
- * var.c(global): when parsing $123, don't limit number to 1000.
-
- * expr.c(v_evaluate): like old evaluate, but assigns result to
- specified variable.
- * expr.c(evaluate): changed to use v_evaluate().
- * expr.c(e0): when parsing literals, use strint() instead of setstr().
-
- * var.c(setstr): when assigning to integers, use v_evaluate() instead
- of strint().
-
-Thu Aug 11 11:33:17 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * var.c(strint): don't change anything until number completely
- parsed; don't clear ISSET flag if parsing fails; fail parse
- if non-integer/non-letter found; default base if copying from
- integer variable; set ISSET if parsing succeeds.
-
- * expr.c(tempvar): set vp->val.i to 0.
- * expr.c(token): when skipping a literal number, don't allow _;
- use isspace() to skip.
- * expr.c(asn): use strint()/setstr() instead of setint().
- * expr.c(e0): added unary ~ and + (posix).
-
- * var.c(global,local): always call substitute on contents of [..];
- free sub when finished eval.
-
- * ksh_limval.h: new file.
- * shf.c: use ksh_limval.h.
- * Makefile.in: added ksh_limval.h to HDRS.
-
-Wed Aug 10 10:57:01 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * c_ksh.c(c_whence): case CFUNC: print exported/traced/undefined,
- do not print function definition.
- * exec.c(findcom): new argument indicated if functions to be
- autoloaded; changed all calls.
-
- * misc.c(ksh_getopt): added # option modifier for typeset.
- * c_ksh.c(c_typeset): changed to use ksh_getopt(); added
- -L, -R, -Z, -l, -u flags; quote variable values when printing;
- generally re-arranged function.
- * table.h: added LJUST,RJUST,ZEROFIL,LCASE,RCASE; deleted FUNCT.
- * exec.c(findfunc): new function.
- * exec.c(define,findcom): use findfunc(); skeleton autoload code.
- * var.c(typeset): added two arguments for initial field width and
- base; changed all calls; deal with LJUST,.. flags; re-arrange to
- have one loop iterating over array; do readonly check before
- changing attributes.
- * var.c(strval): deal with LJUST,.. flags when getting integers.
- * var.c(setstr): deal with LJUST,.. flags when setting strings.
- * var.c(setstr): deal with LJUST,.. flags when setting strings.
- * var.c(arraysearch,tenter): initialize {new,p}->field to 0.
- * table.h: added struct tbl.field.
-
- * siglist.in: changed signal messages to be more or less the
- same as sys_siglist[]; moved SIGUNUSED before SIGBUS.
- * jobs.c(j_print): assume sigtrap[].mess always valid; use
- sigtrap[].mess directly for stopped processes.
-
- * aclocal.m4(KSH_SYS_SIGLIST): new macro like KSH_SYS_ERRLIST.
- * configure.in: use KSH_SYS_SIGLIST instead of AC_SYS_SIGLIST_DECLARED.
-
-Tue Aug 9 10:28:45 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * version.c: removed RCS logs since version numbers don't match
- release numbers.
-
- * configure.in: added AC_PROG_CPP
- * Makefile.in: added rules for generating siglist.out
- * siglist.in,siglist.sh: new files.
- * trap.c(inittraps,deftraps[]): deleted deftraps[]; initialize
- sigtraps[] directly by including siglist.out.
-
- * tree.h: added EXPRSUB for $((..)), re-numbered defines.
- * tree.c(tputS,wdscan): added case for EXPRSUB.
- * eval.c(expand,alt_count,alt_scan): added case for EXPRSUB.
- * lex.h: added SDDPAREN for $((..)).
- * lex.c(yylex): added case for SDDPAREN.
-
- * lex.c(yylex): case SPAREN: match parenthesis using counter instead
- of pushing/poping states.
-
- * lex.h: re-numbered S* defines to be sequential; added SREREAD.
- * lex.c(yyerror): pop SREREADs.
- * lex.c(getsc_): added case for SREREAD.
- * lex.c(arraysub): changed to save whatever is read and return a value
- indicating if brackets matched; changed all calls.
- * lex.c(yylex): if brackets in array reference are not balanced,
- or if array reference not followed by an =, re-read the input.
-
-Mon Aug 8 21:20:08 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * sh.h: fix lseek prototype (from sjg@zen.void.oz.au)
-
- * configure.in,jobs.c: added HAVE_SYSCONF; don't use sysconf() unless
- HAVE_SYSCONF defined (for NetBSD-Feb12 from sjg@zen.void.oz.au).
-
- * jobs.c(put_job): removed PJ_ON_END case and define (not used).
-
-Wed Jul 27 10:19:42 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * made pdksh-5.0.1 distribution
-
- * exec.c(comexec): when doing exec has no command, fall through
- and do variable assignments.
-
- * c_ksh.c(c_let): complain if there are no arguments.
-
- * exec.c(comexec): if XEXEC is set, exit after executing
- (builtin/function) command; deleted FERREXIT code; don't set
- exstat.
- * exec.c(execute): handle FERREXIT; set exstat to rv for all
- cases.
-
- * lex.c,syn.c: changed calls to errorf to yyerror (except the
- on in yyerror()).
- * lex.h(struct source): added errline field.
- * lex.c(yyerror): now a varargs function; if source->errline field is
- non-zero, print it instead of source->line.
- * syn.c(syntaxerr): set source->errline if read EOF in a multiline
- command.
-
-Tue Jul 26 11:22:06 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * lex.h(SYNTAXERR,INP): deleted macros.
- * lex.h(HISTORY): upped to 128 as per POSIX.
- * lex.h,syn.c(multiline): moved from lex.h to syn.c.
- * tree.c(vfptreef): added %R to format I/O redirections.
- * tree.c(pioact): don't output unit more than once; print unit
- only if it isn't the default for the action; print only
- one opening quote for quoted here documents; print <> for
- read-write (was ><).
- * syn.c(zzerr, syntaxerr): replaced zzerr function with new syntaxerr
- function; changed uses of SYNTAXERR to syntaxerr() calls; print
- out the last unused token; if in a multiline command when EOF
- encountered, print token that was unmatched.
-
- * tree.h(TBANG),lex.h(BANG): for POSIX ! keyword
- * tree.c(ptree),exec.c(execute): added case for TBANG.
- * syn.c(restab[]): added ! keyword.
- * syn.c(get_command): added case for BANG (!).
-
- * tree.h(XERROK): new define to allow non-zero exits to be
- ignored in certian circumstances (set -e).
- * exec.c(execute): pass XERROK to recursive execute() calls; set
- XERROK when evaluating conditional part of if/while/until/&&/||.
- * exec.c(comexec): pass XERROK on to functions; don't exit if
- XERROK is set.
-
- * jobs.c(async_pid): new variable needed since async_job may go
- away, but $! should still be expanded.
- * jobs.c(j_async): return async_pid.
- * jobs.c(j_set_async): set async_pid.
-
-Mon Jul 25 14:15:25 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * misc.c(parse_args): changed to use ksh_getopt().
-
- * c_sh(c_set): deleted call to resetopts() - neither POSIX nor
- at&t ksh touch OPTIND when positional parameters are changed.
- * exec.c(comexec): changed resetopts() call to getopts_reset(1) - this
- is not a proper fix - should declare a local optind.
-
- * misc.c(builtin_getopt,ksh_getopt): renamed builtin_getopt to
- ksh_getopt (shorter); changed to use state structure instead
- of static variables; changed all calls; optionally allow + to
- introduce an option; don't skip lone - (or +) in arguments - set
- optind to point to it.
- * misc.c(ksh_getopt_reset): changed to use state structure instead
- of static variables.
- * sh.h(Getopt): new structure for ksh_getopt() state.
- * exec.c(call_builtin): call ksh_getopt_reset().
- * c_ksh.c(c_getopts,getopts_reset): new getopts implementation that is
- POSIX complient and uses ksh_getopt() routine.
- * var.c(setspec): call getopts_reset() when OPTIND set.
- * getopts.c: deleted file.
- * Makefile.in: deleted getopts.c and getopts.o.
- * options.h(FASCIST): deleted option.
-
-Thu Jul 21 09:52:03 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * made pdksh-4.9+mun.5 distribution
-
- * syn.c(get_command),shf.c(shf_fdopen,shf_sopen,shf_emptybuf):
- added cast to alloc()/aresize() calls.
- * sh.h: changed enum flags_enum to enum flags.
- * misc.c(change_flag): changed type of first argument to enum flag.
- * edit.c(set_editmode): change type of static array to enum flag.
-
- * edit.c(x_init): initialize tty chars to -1, except for werase,
- which is set to ^W.
- * edit(x_mode): split oldedchars structure declaration and
- initalization (some old compilers don't like them combined).
-
- * c_test.c: made -h work like -L.
-
-Wed Jul 20 11:12:52 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * config.h.top: moved compile options into options.h; include
- options.h.
- * options.h: new file.
-
- * c_ksh.c(c_fgbg): if !FPOSIX, set return job exit status.
-
- * jobs.c(j_jobs,j_notify): use JF_REMOVE to flag jobs to delete
- after all notification done (to prevent multiple + or - jobs).
-
- * jobs.c(put_job): new funtion, takes argument to specify where
- to put job; changed all calls to put_job_on_front and
- put_job_on_end to use this; put background processes just
- after stopped jobs (instead of at end) (POSIX).
- * jobs.c(put_job_on_front,put_job_on_end): deleted.
-
-Tue Jul 19 10:33:55 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * aclocal.m4(AC_MMAP): copied from autoconf's acspecific.m4 and
- modified to use the MAP_FILE flag if available.
-
- * misc.c(change_flag): ifdef use of FVI/FEMACS/FGMACS.
-
-Mon Jul 18 13:19:29 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * sh.h(async): deleted.
- * var.c(global): call j_async() instead of using async global.
- * jobs.c(j_async,j_set_async()): new functions.
- * jobs.c(j_startjob): new function.
- * jobs.c(exchild,j_waitlast): call j_startjob() to start job.
- * jobs.c(j_sigchld): if any jobs aren't started, note signal
- occured and return without calling wait.
- * jobs.c(j_resume): allow un-reported dead jobs to be fg'd/bg'd;
- if backgrounding, set async job.
- * jobs.c(j_jobs,j_notify,j_waitj,check_job,remove_job): re-wrote to
- deal with posix `known processes'.
- * jobs.c(j_lookup()): if number specified, see if it is a lpid first,
- then check for pgrp.
- * jobs.c(new_job): added functionality of j_newjob().
- * jobs.c(j_newjob): deleted function and all calls.
-
- * tty.c(tty_init,tty_close): new functions which initialize
- tty_fd, tty_state and tty_devtty.
- * jobs.c(j_init,j_change): use tty_init()/tty_close(); changed
- references of ttyfd to tty_fd; moved tty_fd, tty_state and
- tty_devtty to tty.h; call tty_init() if !FMONITOR; save/restore
- tty modes on foreground job completion if FTALKING (was FMONITOR).
- * edit.h(X_chars): new structure for tty driver characters (replaces
- ed_erase, ed_kill, ed_werase, ed_intr, ed_quit); moved prototypes
- for emacs.c and vi.c from proto.h to edit.h; changed all references
- to ed_* to edchars.*.
- * edit.c(x_mode): use tty_state instead of cborig; re-initialize
- tty state from tty_state whenever entering xmode; save tty characters
- in edchars structure.
- * edit.c(x_init): now called from main(); initializes edchars, x_cols,
- and calls x_init_emacs.
- * emacs.c(x_init_emacs): changed erase,kill,werase,intr,quit arguments
- to X_chars argument.
-
-Fri Jul 15 10:35:13 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * io.c(restfd): only flush if fd is 2; use dup2() instead of
- fcntl(F_DUPFD) (2 system calls instead of 3).
-
- * ksh_wait.h(WEXITSTATUS): changed mask from 0x7f to 0xff.
-
- * tty.h: added TTY_state structure.
- * tty.c: new file - contains get_tty() and set_tty().
- * edit.c(x_init,x_mode): use get_tty() and set_tty().
- * jobs.c(j_waitj,j_resume): save/restore tty modes of stopped
- jobs, as per POSIX.1, B.2, job control; for foreground jobs,
- save tty state after successful completion, restore tty state
- after non-successful completion (signaled, non-0 exit, stopped).
-
- * misc.c(options): changed "alternations" to "braceexpand" (this
- is what bash uses - no need to invent new option names); changed
- ALTERNATIONS define to BRACEEXPAND, same for FALTERNATIONS to
- FBRACEEXPAND.
-
- * jobs.c(check_job): if process died of SIGINT or SIGPIPE, leave
- job state as PEXITED (not PSIGNALLED).
- * jobs.c(j_print): if printing short notice, ignore SIGPIPE the
- way SIGINT is ignored.
-
- * exec.c(comexec): flush shl_out after 'not found' message.
-
- * c_ksh(c_kill): re-wrote function (again) to handle posix
- options (-s, --, etc.) and posix -l output.
-
- * configure.in: added strcasecmp function check.
- * missing.c(strcasecmp): define strcasecmp function if not available.
- * trap.c(gettrap): use strcasecmp when comparing signal names.
-
- * var.c(global): expand $! to nothing if there haven't been any
- asynchronous processes started yet.
-
- * misc.c(options): added posix option (set automatically if
- POSIXLY_CORRECT env variable is set or if POSIXLY_CORRECT config
- define is defined)
- * var.c(special,setspec): added POSIXLY_CORRECT.
- * config.h.top: added POSIXLY_CORRECT define.
- * main.c(main): set FPOSIX if POSIXLY_CORRECT is defined.
- * POSIX: new file describing what the posix flag controls.
-
-Thu Jul 14 10:53:15 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * jobs.c,sh.h(killpg): moved killpg define to sh.h.
-
- * jobs.c(exchild): set async variable when starting background
- processes.
- * jobs.c(j_resume): print [job-num] before command when backgrounding;
- print to stdout instead of stderr.
- * c_ksh.c(c_fgbg): call builtin_getopt to skip possible --, complain
- about unknown options.
-
- * jobs.c(held_sigchld): new global variable.
- * jobs.c(j_sigchld): if any jobs aren't started, set held_sigchld and
- return.
- * jobs.c(exchild,waitlast): after setting JF_START, if held_sigchld
- set, call j_sigchld().
-
- * jobs.c(exchild): added/initialized ppid field to struct job; deleted
- global is_child.
- * jobs.c(waitfor): don't wait for a process that isn't a child of
- the current process.
- * jobs.c(j_exit): kill stopped jobs owned by current process only.
-
- * jobs.c(check_job): don't do monitor stuff for XXCOM jobs, but do
- set up notification.
- * jobs.c(j_waitj): added JW_NOTIFY flag to print job notification
- messages.
-
- * jobs.c(exchild): remove !XPIPEI condition - we now close pipe so
- pipeline doesn't have to call waitlast().
- * exec.c(execute): case TPIPE: no need to restore 0 or call waitlast()
- since exchild() handles everything.
-
- * jobs.c(remove_job): set last_job to 0 if we are removing it.
- * jobs.c(waitlast): check if last_job is 0.
-
- * jobs.c(struct job): combined started, waiting, interactive
- field into flags field; added JF_* flags; changed JW_NONOTIFY
- to JW_NOTIFY and changed all calls to j_waitj() to reverse
- this flag.
-
- * jobs.c(exchild): ignore SIGTSTP, TTIN, TTOU for `command` jobs.
-
-Wed Jul 13 09:28:34 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * main.c(main): when checking if FMONITOR set on command line,
- use 127 instead of -1 (signed vs unsigned char problem).
-
- * tree.h: renumbered, XEXEC, XFORK, ... and DOBLANK, DOGLOB, ...
- to use bits in order (instead of 0 5 2 4...).
- * jobs.c(j_init): don't set sigtrap[SIGCHLD].sig_dfl = 1 as a
- forked child may be a shell that needs to trap SIGCHLD.
-
- * tree.h(XPCLOSE,XCCLOSE): flags for close in parent, close in child.
- * jobs.c(exchild): added third argument - a file descriptor - if
- flags has XPCLOSE, close fd in parent, if flags has XCCLOSE, close
- in child.
- * exec.c(execute): pass input side of pipe to exchild() so it can
- be closed in the child.
-
-Tue Jul 12 10:21:57 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * main.c(main): let ignoresig() handle SIGTERM.
- * jobs.c(exchild): let restoresigs handle SIGTERM.
-
- * lex.c(yylex): don't parse array references inside double quotes
- (partial fix).
-
- * emacs.c(x_print): use shprintf instead of shellf so the output
- of bind can be redirected.
-
- * trap.c(deftraps): added SIGINFO (from jconklin@netcom.com).
-
-Fri Jul 8 09:37:51 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * made pdksh-4.9+mun.4 distribution
-
- * Makefine.in: added $(LDSTATIC) to LDFALGS to make static
- linking easier (suggested by sjg); use cp -p when creating
- distributions to preserve file dates.
- * configure.in: set LDSTATIC in Makefile if present in environ
- when configure is run.
-
- * sigact.c(sigsuspend): when calling 4.2bsd sigpause, pass *mask,
- not mask.
-
- * main.c(main): fixed up initialization of PWD (free memory, print
- more informative message).
-
- * misc.c(getcwd): range check backwards.
-
- * c_sh.c(setsig): set sa_flags/sa_mask.
-
- * edit.c(init_editmode),main.c,proto.h: deleted function - not needed
- since VISUAL/EDITOR are special.
-
- * lex.c(set_prompt),table.h: take out PS3.
-
- * c_sh.c(c_umask): handle multiple actions in symbolic mode clauses
- (eg, u+r-w); handle X (eg, o+X); ignore s (eg, u+s).
-
- * shf.c(shf_fillbuf): continue reading if we get an EINTR.
- * shf.c(shf_emptybuf,shf_write,shf_putchar): continue writing if we
- get an EINTR.
-
-Thu Jul 7 10:19:24 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * sigaction,sigprocmask: changed NULL third argument to
- (struct sigaction *) 0.
- * sh.h(kshpid): changed type from int to pid_t.
- * proto.h(do_ulimit): removed do_ulimit() declaration.
- * vi.c(complete_word): removed unused variable pos.
- * syn.c(pipeline,elsepart): removed unused variable c.
- * jobs.c(exchild): deleted variable s (assigned but not used).
- * history(hist_init),shf.c(shf_gets): changed variable e to end
- because there is a global e.
- * exec.c(do_selectargs): removed secondarg argument; changed return
- (char *) 1 to (char *) 0; changed all calls.
-
- * io.c(canseek): use fd argument instead of 0.
-
- * lex.c(readhere): don't use fixed sized buffer (line).
-
- * expand.h: changed multi-statement macros to use do {..} while (0);
- changed temporary variable vp to vp__ to avoid lint complaints.
-
- * aclocal.m4(KSH_DUP2_CHECK): define F_GETFD/F_SETFD if not
- already defined.
-
- * etc/profile, etc/ksh.kshrc: replaced with new versions from
- Simon J. Gerraty (sjg@zen.void.oz.au).
-
-Wed Jul 6 10:09:55 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * jobs.c(killpg),configure.in: restored use of killpg() - some
- systems don't understand kill(-pgrp, signal) (ultrix 2.2);
- added test for killpg() in configure.in.
-
- * trap.c(inittraps): changed initialization of sigtraps - was
- using -1 in deftraps[] as end of table marker but some systems
- (eg, ultrix 2.2) define signals with -1 values (SIGPWR).
-
- * Makefile.in(mandir,install): fixed mandir value; added /
- in man installation; prefixed ksh.1 with $(srcdir).
-
- * jobs.c(j_init): Ignore failure of TIOCSETD.
-
- * misc.c(options[]): changed "vicomplete" to "vitabcomplete".
-
- * emacs.c(x_e_putc,x_e_puts,x_debug_info): x_e_putc()/x_e_puts() are
- the x_putc()/x_puts() functions from ksh4.9 edit.c (they got lost
- in the merge); same for x_debug_info(); changed x_e_putc/x_e_puts
- to call x_putc/x_puts.
-
-Mon Jul 4 09:29:05 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * made pdksh-4.9+mun.3 distribution
-
- * main.c(remove_temps): use unlink() instead of remove(); delete
- remove() define.
-
- * sh.h(func_heredocs, struct env): added func_heredocs for here
- documents in functions; added func_parse field to struct env
- - set when a function is being parsed.
- * lex.c(readhere): if e.func_parse, save temp file in func_heredocs.
- * syn.c(get_command): increment/decrement func_parse when parsing
- functions.
- * main.c(remove_temps,reclaim,leave): added remove_temps(); make
- reclaim() call remove_temps(); make leave() clean up function
- here documents.
-
- * aclocal.m4(KSH_TIMES_CHECK): new test - define TIMES_BROKEN
- if times() doesn't exist or if it always returns 0.
- * acconfig.h(TIMES_BROKEN): new define.
- * missing.c(ksh_times): new function.
- * ksh_times.h: new file.
- * c_sh.c,jobs.c: changed <sys/times.h> to "ksh_times.h"
- * c_sh.c,ksh_time.h(CLK_TCK): moved CLK_TCK define from c_sh.c
- to ksh_time.h (needed in missing.c).
-
- * syn.c(get_command): case TIME: don't call pipeline() with CONTIN
- flag.
-
- * c_sh.c(c_times): combined some printfs().
-
- * jobs.c(j_jobs,j_kill,j_resume,waitfor): block SIGCHLD before
- calling j_lookup() or looking at jobs list - avoids potential
- problems with remove_job() being called in signal handler.
-
-Sun Jul 3 11:09:01 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * exec.c(do_selectargs, selread, pr_menu): re-wrote do_selectargs to
- let c_read() to most of the work; deleted selread; make pr_menu
- calculate width/ncolumns each call so select can be used recursively.
-
- * configure.in, aclocal.m4(KSH_TERMIOS_H, KSH_TERM_CHECK): replaced
- KSH_TERMIOS_H with KSH_TERM_CHECK; removed calls to
- tcgetpgrp/tcsetpgrp - there is a seperate test for this.
-
- * main.c(main), sh.h: move getcwd() declaration to sh.h.
-
- * eval.c(expand,varsub): added XNULLSUB case to deal with "$@"
- (and "${foo[@]}") when $# (or ${#foo}) is 0.
-
- * eval.c(expand,varsub): removed free_me field - let reclaim() take
- care of it.
-
-Wed Mar 9 00:50:12 1994 Simon J. Gerraty (sjg@zen.void.oz.au)
-
- * var.c (setstr): don't set ALLOC flag if vp.s is NULL.
-
-Thu Jun 30 10:16:44 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * c_sh.c(c_read): ignore null characters; use builtin_getopt()
- instead of explicit parsing; removed -e option (neither at&t ksh
- nor POSIX have this); added -s option (put line in history, at&t ksh);
- if no variable specified, use REPLY (at&t ksh).
-
- * exec.c(do_selectargs): use Xstring macros to deal with saving
- input (was static, growing, buffers); flush shl_out after
- shellf().
-
- * vi.c(expand_word,complete_word): deleted call to free_edstate
- since already done by restore_edstate().
- * var.c(global): in 'if !letter(c)' block, deleted !c from
- 'if (!c || !n[1])' - don't know why it was added since it makes
- no difference to what is returned.
-
- * syn.c(dogroup): removed onlydone argument since it is only
- used in the while/until statements, where "while command; done"
- is not allowed anyway; Changed all calls.
-
- * misc.c(options[]): allow -i to be specified on the command
- line.
-
- * exec.c(iosetup): if stderr (fd 2) is being re-directed,
- re-open shl_out to clear any errors.
- * main.c(quitenv): if restoring fd 2, clear any write errors
- * io.c(initio): initialize shl_out, shl_spare for writing
- (was SHF_GETFL).
-
- * main.c(main): ignore SIGQUIT if talking.
-
-Wed Jun 29 11:11:34 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * c_sh.c(c_exit): removed jobs/really quit stuff - exit should
- always exit.
- * main.c(shell): made reallyquit a local variable.
- * sh.h(reallyquit): deleted reallyquit
-
- * exec.c(comexec), main.c(main), misc.c(change_flag), jobs.c:
- ifdef'd use of FMONITOR.
- * sh.h, misc.c: define FMONITOR option only if JOBS defined.
-
- * c_sh.c(c_wait): POSIXized: option parsing (of no options);
- return 0 if not given any arguments; deal with multiple arguments.
- * jobs.c(j_lookup): changed second argument to return an integer
- error code, added defines for error codes, added error message
- array; changed all calls to use new conventions.
- * jobs.c(waitfor): returns -1 if job not found; added argument
- to specify if notification messages should be suppressed.
- * jobs.c(j_waitj): added flags argument instead of intr argument;
- added JW_STOPPEDWAIT flag to wait for stopped jobs to complete;
- added JW_NONOTIFY flag to suppress notification of normal
- job termination.
-
-Tue Jun 28 16:13:10 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * c_ksh.c(c_jobs): added -n and -p options, allow job ids to be
- specified for -l option.
- * jobs.c(j_jobs): added new arguments to deal with -n and -p options.
-
- * shf.h(SHF_BSIZE): reduced size to 512 to reduce memory requirements
- (I/O is used mostly for one line messages).
-
- * config.h.bot: removed necessity for tty process groups to define
- JOBS, added necessity of signal blocking/pausing.
-
-Mon Jun 27 21:49:52 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * jobs.c(exchild,j_print,j_waitj,j_jobs,check_job): exchild() - removed
- commented out shf_flush() calls; j_print() - print a space between
- status reports when lflag < 0, changed flag argument to use
- long/medium/short defines; Changed Job.notify field to use
- long/medium/short defines; j_waitj() - instead of calling j_print(),
- set j->notify to print the job; j_jobs() - clear j->notify so user
- won't be notified twice if a job finishes before a jobs command;
- check_job() - put job on front of list only if it is stopped.
-
- * main.c(main): pass flag to j_init() indicating if -m flag set/cleared
- on command line; don't initialize ttyfd.
- * sh.h: delete ttyfd.
- * jobs.c(j_init,ttyfd,check_job): made ttyfd static; re-worked j_init()
- to initialize ttyfd, initialize FMONITOR if not set by command line,
- initialize shl_j for asynchronous job notification;
- check_job() - use shl_j, look through saved fds to find real
- standard-error.
-
- * jobs.c(TTY_PGRP, ttypgrps_ok): modified conditions so job control
- is useful without tty process groups; added ttypgrps_ok flag that
- indicates if tty process groups should be set up; modifications so
- job control useful if ttypgrps_ok not set.
-
- * main.c(main): set FTALKING if 0 and 2 are tty as specified in POSIX
- (was 0 and 1).
-
- * misc.c(parse_args): do POSIX option processing for -A, -c and -o
- (allow -onoglob, -ctrue).
- * main.c(main): don't set up shl_stdout before/after parse_args() since
- lone -o on command line no longer accepted; remove code to allow
- -c with no options to read from stdin (at&t khs does this but POSIX
- requires an option to -c).
-
-Thu Jun 23 17:46:54 NDT 1994 John Rochester (jr@panda.cs.mun.ca)
-
- * trap.c(cleartraps): added special case for clearing trap 0 from
- ksh-4.9 sources.
-
-Thu Jun 23 10:17:03 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * misc.c(builtin_getopt): print error messages for unknown option,
- missing option; reset state if argv is 0.
- * c_ulimit.c(c_ulimit): let builtin_getopt() print error messages.
- * exec.c(call_builtin): call builtin_getopt() with 0 argv.
-
- * c_sh.c(c_unset): added -v option (POSIX); use builtin_getopt() to
- parse arguments; removed bogus comment about global() and special
- variables; don't allow read-only variables to be unset (POSIX).
-
- * var.c(unset, unsetspec): when unsetting a special variable, call
- unsetspec(); unsetspec() new function.
- * mail.c(mbset, mcheck): check that path is not 0 before calling stat
- (so mbset() can be called with 0 when MAIL is unset); deleted #if 0'd
- declarations of munset, mballoc and maddmsg.
-
- * misc.c(parse_args): pass argv+i+1 to set_array (not argv+i); when
- skipping arguments, leave i just before the NULL.
-
- * exec.c(echo): flush shl_out when done.
-
- * shf.c(shf_close): always used to return EOF.
-
- * trap.c(trapsig): skip error handlers when checking for PARSE or LOOP.
-
-Wed Jun 22 10:24:09 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * sh.h(C_IFSWS), misc.c(initctypes): added and initialized C_IFSWS
- (IFS white space).
- * c_sh.c(c_read): print continuation prompt if line ends in backslash;
- multiple non-white-space IFS chars delimit fields; strip trailing
- IFS-white-space from last variable; watch out for backslash followed
- by EOF.
- * eval.c(expand): only do field splitting on the results of
- parameter/command substition (POSIX, !v7-sh); multiple
- non-white-space IFS chars delimit fields.
-
- * eval.c(expand,alt_expand): removed NOALT tests since it could
- never be set; added return after call to alt_expand() in expand().
-
-Mon Jun 6 10:12:41 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * misc.c(setctypes, initctypes): setctypes - don't allow leading null
- in IFS (IFS="" could cause problems, 0 is already added);
- initctypes - don't use a leading null.
-
- * sh.h, eval.c: move definition of ifs0 from eval.c to sh.h; handle
- null ifs0.
- * var.c(setspec): set ifs0 to first character of IFS.
-
- * lex.c(yylex): when parsing ${..}, array references were not being
- null terminated.
-
-Fri Jun 3 12:28:06 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * var.c(export): changed to use memcpy() instead of loops.
-
- * eval.c(varsub, expand): check for #foo[@] in addition to #foo[*];
- handle ${foo[*]} and ${foo[@]} - added free_me field to struct Expand
- so pointer vector can get freed.
-
- * c_sh.c(c_dot), main.c(include): set up positional parameters if
- any are specified; Added argc,argv args to include(); changed all
- calls to include(); change include() to return 0 or 1 - caller
- can check exstat if desired; c_dot() should return 1 if can't open
- file (was -1).
-
- * c_sh.c(c_brkcont): warning message could call getn() with NULL - save
- original number and print it.
-
- * main.c(main): set $0 to first argument when -c used, ie,
- "sh -c cmd-string this-is-$0 argumernts..."
-
- * exec.c(iosetup): print "cannot open" if IOHERE fails.
-
- * io.c(errorf): set exstat to 1.
-
- * exec.c(search): assume mode is R_OK or X_OK (not 0/1 - 0 is F_OK, we
- want R_OK); changed all calls to pass R_OK/X_OK.
- sh.h: define R_OK,W_OK,X_OK,F_OK if not defined.
- eaccess(): changed all calls to use [RWXF]_OK.
-
- * sh.h(flag[], shell_flags[], Flag()): Renamed flag[] array to
- shell_flags[] to avoid conflicts with other uses of flag; Changed
- all references to flag[] to Flag(); defined Flag() to cast its arg
- to an int (for old pcc based C compilers).
-
- * vi.c(iswordch): use letnum() instead of isalnum || _.
-
- * misc.c(parse_args): call set_array() to deal with -A flag.
- * var.c(set_array): new function.
-
-
-Fri Jun 3 10:22:26 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * eval.c(substitute): afree(s).
-
- * var.c(global,local), sh.h: ARRAYMAX: new define - max index of an
- array; changed 511 constants to this; changed global() and local()
- to use array_ref_len() instead of arraysub().
-
- * expr.c(token): deleted unneeded arraysub() decl.
-
- * lex.c(arraysub), proto.h: made static, removed unused arguments,
- changed callers; removed prototype from proto.h.
-
- * ChangeLog: changed descriptions from func(file) to file(func).
-
-Wed Jun 1 09:17:50 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * made pdksh-4.9+mun.2 distribution
-
- * Makefile.in: added RCSFILES macro and rcs-ci target.
-
- * configure.in: add termio.h to the AC_HAVE_HEADERS() call.
-
- * sh.h, main.c, edit.c, misc.c: use EXTERN for aperm, x_cols,
- builtin_optind and builtin_optarg in sh.h, delete definitions
- in main.c, edit.c and misc.c.
-
- * io.c(maketemp): changed sizeof(PATH) to sizeof(path).
-
- * aclocal.m4(KSH_VOID,KSH_DUP2_CHECK): test that a void * variable
- can be used (Ultrix 2.2 compiler doesn't do this); added ifdef
- HAVE_FCNTL_H to dup2 test.
-
- * aclocal.m4, configure.in, sh.h, tree.c, io.c, shf.c: added
- new config test KSH_PROTOTYPES to check for function prototypes
- (MIPS RICS/os 5.0 C compiler isn't STDC and it can't mix <stddef.h>
- with <varargs.h>). Removed stdarg.h test (now redundent). Changed
- all varargs functions to use HAVE_PROTOTYPES instead of
- HAVE_STDARG_H && STDC.
-
- * eval.c(alt_scan): changed type of endc param from char to int to
- avoid problems with mixing prototype declarations and K&R
- definitions.
-
- * main.c(main), sh.h: added plain getcwd() decl to main(), removed
- ARGS() version from sh.h (some systems have getcwd() but don't
- declare it, some have getcwd() with a size_t arg 2, some have
- an int arg 2).
-
- * misc.c(memset,memmove): changed the second memset() to memmove().
-
- * c_sh.c(clocktos): changed #if CLK_TCK ... to if (CLK_TCK.. since
- CLK_TCK is not always defined to a number (may be a _sysconf())).
-
-Tue May 31 10:49:16 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * configure.in, Makefile.in: added code to set GCC_WARNFLAGS from
- $(srcdir)/Warn-flags if gcc is being used; Took -Wall, etc.
- out of CFLAGS, took -Dno_RCSids out of DEFS. Added install.sh to
- DISTFILES, grabbed copy of install.sh from autoconf (who grabbed
- it from X11R5).
-
- * io.c(errorf,shellf,shprintf),shf.c(shf_fprintf,shf_snprintf),
- tree.c(fptreef,snptreef): don't use ansi decls with old style
- varargs; changed ifdef __STDC__ to ifdef HAVE_STDARG_H.
-
- * jobs.c(j_init): changed getpgrp() call to getpgID(), defined getpgID()
- appropriately for BSD vs POSIX/SYSV getpgrp.
-
- * expand.h, ksh_dir.h, ksh_stat.h, ksh_time.h, ksh_wait.h, shf.h,
- tty.h: added RCS $Id: ChangeLog.0,v 1.1 1996/08/14 06:19:10 downsj Exp $'s.
-
- * acconfig.h: updated SIGSET_T comment: unisgned int -> unsigned.
-
- * aclocal.m4(KSH_CLOCK_T,KSH_TIME_T,KSH_SIGSET_T): make sure
- type is a word (same fix as was done for more_t, et.al.).
-
- * aclocal.m4(KSH_VOLATILE): check that the compiler can deal with
- volatile pointers (dec/pmax ultrix 4.2 compiler can't).
-
- * misc.c(parse_args): added skelatal code for dealing with -A.
-
- * var.c,proto.h(skip_varname): new function; deleted isassign()
- function, which is no longer called. Changed typeset(var.c)
- to use skip_varname().
-
- * var.c(strint): fail if base is not in the range 2..36; set variable
- base according to first base seen; generate an error if a non-alnum
- char is seen (1^A was the same as 11).
-
- * var.c(strval): for integer variables, output base if != 10.
-
- * sh.h: fixed typo in x_cols define (#defined -> #define).
-
-Fri May 27 16:49:29 NDT 1994 Micharl Rendell (michael@panda.cs.mun.ca)
-
- * made pdksh-4.9+mun.1 distribution
-
- * finished autoconf'ing source code.
-
-Fri May 20 16:47:06 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * c_ulimit.c(c_ulimit) (was do_ulimit.c(do_ulimit)): major rework;
- deal with combinations of getrusage and ulimit, use options at&t
- ksh uses (-SHa..).
- * misc.c(builtin_getopt): yet another getopt routine for builtin
- commands
- * misc.c(parse_args), c_sh.c(c_set), main.c(main): custom option
- parsing routine for command line/set options. Lots of changes
- to main() to incorporate this (easier to follow).
- * c_test.c(c_test): added -e (file exists) test.
-
-Fri May 5 12:16:46 NDT 1994 Michael Rendell (michael@panda.cs.mun.ca)
-
- * numerous changes from old Notes.4-9 file:
- - c_ksh.c:
- - calls to errorf identify what function the error is in
- (eg, errorf("print: bad -u option");)
- - added array stuff (lots of places)
- - table.c
- - lex.c
- - var.c: +arraysearch(), +basename()
- - c_sh.c(c_exit), main.c(shell), sh.h:
- - added reallyquit flag to deal with stopped jobs at exit time;
- only two exit commands (or eofs) in a row will work. in
- shell(), set exstat from execute value.
- - c_ksh.c(c_print):
- - handle \\ at end of string better (don't skip the null)
- - c_ksh.c(c_whence):
- - stop looking as soon as we get a failure
- - pass flag[FTRACKALL] to findcom() instead of 0
- - c_ksh.c(c_alias):
- - print '%s alias not found' if not found
- - c_ksh.c(c_jobs):
- - handle -l option (list pid)
- - c_ksh.c(c_kill):
- - two column -l output to try to keep it on one screen
- - c_sh.c(c_read):
- - skip IFS at start of line "echo ' a b' |(read a b; echo $a)"
- should print a, not nothing.
- - changed EOF check to set all vars to null (same way \n is
- handled)
- - eval.c(comsub):
- - after compile(), return if t is NULL
- - use setfileno() instead of fileno(x) = .. (see sh.h changes);
- - exec.c(iosetup):
- - set exstat if redirect fails
- - exec.c(fd_clexec):
- - check that fd >= 0
- - exec.c:
- - change SHARPBANG ifdef code - everyone uses scriptexec().
- ifdef is put around open/read/parse code in scriptexec().
- [code cleanup]
- - exec.c(search):
- - eaccess test out side of loop: must be regular file to exec it
- (like test in loop)
- - eval.c(expand):
- - added while getc() == 0 in XCOM
- [a null in the output of a file would be treated as eof and
- waitlast would not be called]
- - eval.c(trimsub):
- - '%' subst: use ATEMP, not APERM
- - eval.c(tilde): use Xinit et. al., instead of fixed length buffer
- - getopts.c(getopt): rename getopt() to ksh_getopt() to avoid
- problems with prototypes in system #include files.
- - io.c(fopenshf):
- - call clearerr(fd) if already open
- - use F_GETFL to determine appropriate mode for fdopen() call
- instead of opening everything for read/write
- - use ifdef _FSTDIO instead of ifdef _BSDI (_FSTDIO is used in
- 4.4bsd, NetBSD, FreeBSD and other non BSDI environs)
- - lex.c(ungetsc): don't decrement if str == null, remove nullstr hack
- - lex.c(yylex):
- - \ at eol: call Xfree before goto Again
- - use memset() to clear ident, instead of while loop
- - syn.c(get_command): renamed from command() to get_command() to
- avoid conflicts with command(main.c).
- - sym.c(get_command):
- - allow A=B <alias-name> to work (alias was not being expanded)
- - allow `if .. if .. fi fi' to work (no ; after group terminator
- (fi , esac, done, ), })
- - allow `alias FI=fi ; if .. if .. fi FI' to work (alias
- expansion after group terminator)
- - do not assume resize returns same pointer
- - tree.c(pioact):
- - handle IORDWR case
- - added leading quote for file in IOHERE case
- - var.c(special):
- - add MAILCHECK check
- - var.c(setspec):
- - add MAILCHECK case (doesn't do anything yet)
- - var.c(strint):
- - handle null vp->val.s
- - eval.c(sh.h, expand), misc.c(options[]):
- - enable alternations only if alternations flag set
- (set -o alternations). This is so (att ksh) scripts that don't
- expect alternations won't break.
- - added notify option (asynchronous job completion notification)
- - added vicomplete to enable tab char as file name completion
- char in vi (this is likely to go away - exits for historical
- reasons)
- - jobs.c, main.c, sh.c, trap.c:
- - define/use SIG_HDLR instead of void
- - eval.c(expand): alt_expand() does not return a value so don't test
- it, just return. Also changed decl of alt_expand() to reflect
- reality.
- - emacs.c(x_emacs): first return returns random value (i); change to
- return 0. Also changed the way interrupts are returned to called
- (return -2 means interrupt).
- - c_sh.c(c_brkcont): at&t ksh allows breaks/continues outside of
- loops, 4.9 prints an error and breaks out of all env's (if, case,
- etc.). Fixed to act like at&t (ie, allow bogus continues), except
- a warning message is printed. (Some HP-UX shell scripts actually
- have continues outside of loops...)
- - main.c(shell): parameter s should be volatile as it is used after a
- setjmp.
- - edit.c(promptlen): handle tabs, backspaces...
- - cleaner fix to the ^C/source->line problem: in pprompt(lex.c),
- convert ! to source->line+1 (same in promptlen(edit.c)), increment
- source->line after a (non-empty, non-eof) line has been read
- (before call to histsave()). To be pedantic, also adjust
- position of source->line++ in SHIST in case PS9 is ever used.
- Remove code in shell(main.c) that does the source->line--,
- remove the source->line-- for eof and empty line in from
- getsc_(lex.c).
- - trap.c(sigtrap[]): do not depend on signal number matching position
- in initialization array. Use second table in which order does not
- matter to initialize sigtrap[] array. Easier to read/port, and
- generally less fragile. requires call to inittraps() in main.c.
- - trap.c(cleartraps): need to clear Sigact flags/mask after use
- (actually, declare a local struct sigact and use that instead of
- Sigact)
- - exec.c(execute): case TSELECT: no USE_SIGACT code for call to
- signal(); case TPIPE: don't call waitlast() if XXCOM since
- waitlast() will be called in expand(); 4.9 code that set and
- then cleared the XEXEC flag in the TPIPE case not added since
- it was ifdef'd out, also the code to not exit if XPIPEI flag
- set was not added; 4.9 XXWHL flag not added (don't flush stdin
- if in a while loop) since this problem fixed (I hope) by shf stuff.
- - ttyfd{sh.h/lex.c}: use EXTERN/_I_ to initialize ttyfd. Remove from
- lex.c
- - interrupted reads: instead of testing sigchld_caught after reads
- fail, continue them if errno == EINTR.
- - edit.c(x_getc): check for EINTR, and continue reading if so.
- - lex.c(getsc_): check for EINTR, and continue reading if so.
- (don't check return of x_read() - check has already been done)
- - exec.c(selread): check for EINTR, and continue reading if so.
- - history changes:
- - history.c:
- - histrpl(): bounds check doesn't take global flag into
- account - move check into loop and past loop.
- - c_fc(): if pattern is the empty string, histrpl()
- goes into infinate loop. Start searching for = after first
- char (this is what at&t ksh seems to do).
- - c_fc(): `fc -l first' should list at most 16
- commands according to at&t manual.
- - findhist(): re-wrote: shorter, easier to follow. Now
- returns an int. (used only by vi code)
- - use COMPLEX_HISTORY's allocated history array in
- EASY_HISTORY: common init_histvec(), sethistfile() and
- sethistsize() functions.
- In the process, hist_open() went away. Use histsize
- instead of HISTORY in hist_init() and hist_finish()
- #ifdefs in lex.h, table.h,
- var.c disappear, history variable definitions in lex.c
- disappear.
- - hist_init(COMPLEX_HISTORY): move hstarted = 1 to after the
- FTALKING test.
- - hist_finish(): don't open hname if its null
- - histrpl(): made static, use ARGS in decl
- - made current and curpos static
- - changes to allow embedded newlines in commands:
- - histsave(): trash only trailing newline
- - hist_init(): read in null terminated lines instead of
- newline terminated
- - hist_finish(): write null terminated lines
- - make multiple line command appear in single history line
- (EASY_HISTORY only):
- - added histappend() to append new command to last
- command
- - added call to histappend() in getsc_(lex.c) (also: only
- adjust source->line if not multiline).
- - lex.h:
- - remove second decl of history if !EASY_HISTORY
- - tree.c(ptree): case TCOM: check if t->vars or t->args is 0
- - vi.c(x_vi): ^D anywhere in command line is eof ($ foobar^D exits).
- at&t ksh ignores ^D in middle of line
- - edit.c:
- - don't need to include string.h - included in stdh.h
- - init_editmode(): in at&t ksh, VISUAL takes precenence over
- EDITOR, so put it first. Also, at&t ksh doesn't use FCEDIT so
- trash it.
- - moved initialization of ed_* from x_read() to x_init() since
- thats where they are set from tty structs.
- - x_init(): set ed_intrc, ed_quitc for _BSD & _POSIX_TERM ifdefs
- - send output to shlout (instead of stdout - at&t ksh writes to
- stderr)
- - made x_do_init static.
- - exit.c(x_getc), lex.c(yylex): restart interrupted reads in
- x_getc(), changed read-restart in yylex() to only effect call
- to read().
- - syn.c(thenpart): then THEN is not optional - generate a syntax
- error if no THEN. (ie, `if true ; fi' is not legal).
- - syn.c(get_command): don't accept keywords after re-directory (eg,
- `> /dev/null if true ; then echo hi ; fi' is not legal).
- - vi.c: handle \ and ^[ in command mode ala at&t ksh (filename
- completion)
- - syn.c(thenpart), syn.c(elsepart): calling token(0) when they want a
- keyword (always worked 'cause tpeek() is always called before, with
- the keyword flag). Fix: call token(KEYWORD|ALIAS) (at&t ksh does
- alias expansion here). Question: pass CONTIN as well?
- - syn.c(get_command): LWORD/MPAREN case: do alias expansion when
- getting open brace ({). CASE case: ditto for `in' and `esac'.
- IF case: ditto for `fi'. FUNCTION case: dito for open brace ({).
- - syn.c(dogroup): alias expansion when getting `do' and `done'.
- - syn.c(wordlist): alias expansion when getting `in'.
- - syn.c(nested): alias expansion when getting `)', `}'
- - syn.c(casepart): alias expansion when getting `esac' or `;;'.
- Also removed use of cf variable - it does nothing.
- - eval.c(expand): case CSUBST: '#'/'%' - increment st so nested
- substitutions work.
- - var.c(typeset): INTEGER && no assignment: memory was being freed
- and then used (there was even a comment saying it was being
- done...)
- - lex.c, lex.h, exec.c, main.c:
- added shf_{open,fdopen,close,gets}() routines so stdio wasn't
- used. When reading a command file under osf/1, stdio would
- mess up the read pointer when a child exited: the exit flushed
- all open files and flushing a file open for reading changes the
- current read position (does a seek to where the next char would
- be read). This position is then used by the parent process,
- who thinks the read position is still at the end of the buffer
- it read.
- - c_sh.c:
- use shf_*() routines avoids two bugs in read:
- - on sunos 4.1.3, a read would gobble up a stdio buffer and
- never put it back (ie, lseek backwards). Neither a
- fflush() nor a fseek(x, 0L, 1) fixed the problem.
- (see Bug 26)
- - on linux, stdio knows its current offset and seeks there
- before reading a buffer. This causes grief when the shell
- replaces file descriptors behind stdio's back (ie, all the
- time).
- $ read x << EOF
- hi
- EOF
- $ cat > /dev/tty << EOF
- 1:abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
- 2:abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
- 3:abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
- EOF
- $
- the cat picks up reading at the offset where the read
- command left off (ie, at bcdefg... - the 1:a are skipped).
- - exec.c(comexec): built-in c_exec && no args: close the saved fd's
- (were thrown away). Also, set close-on-exec flag for fd's > 2,
- as per at&t manual.
- - lex.c(yylex): only accept 1 digit before a redirection (eg, 1> is
- ok, 1abc> is not)
- - exec.c(iosetup): only accept 1 digit after a dup-redirection
- (eg, >&1 is ok, >&1abc is not)
- - exec.c(iosetup): use O_APPEND flag for >> redirections; use O_CREAT
- flag for <> redirections. (re-organized to accumulate open() flags
- and do one open() call); changed error message to know about dup
- failing.
- - c_sh.c(c_umask): umask should have leading 0 - doesn't when umask
- has 3 digits (eg, `umask 222; umask' prints 222 instead of 0222)
- - c_sh.c(setsig): declare local struct sigaction and use it so
- sa_flags doesn't have to be cleared (also to try to keep away from
- global vars).
- - main.c(main):
- - don't go set TALKING if name starts with -.
- - read $HOME/.profile (not .profile)
- - main.c(main): re-wrote option parsing code
- - edit.c(init_editmode): don't check FCEDIT
- - if set -o vi/emacs/gmacs on command line, don't set edit mode from
- FCEDIT/EDITOR/etc.
- - var.c(setspec): FCEDIT should not magicly change edit mode; VISUAL
- and EDITOR should (EDITOR only if VISUAL is not set)
- - changed noclobber char from ! to | (this is what at&t ksh uses)
- - exec.c(iosetup): use O_EXCL flag if FNOCLOBBER set and >| not used
- - c_sh.c(c_set): don't clear FERREXIT if FTALKING is set; although
- some ksh manuals say -e is ignored for interactive shells, they
- all seem to honour the -e flag for interactive shells.
- - vi.c: reset history position to the end after a line is modified
- - `(( 1 + 2 ))' no longer prints `+: bad expression'!
- - lex.c(yylex): added parenthesis counting so `(( ((1+2)) ))' no
- longer generates a syntax error
- - expr.c(intvar): if strint() fails, give bad number error
- (`let 1+foo' should fail)
- - `echo hi 1abc123> /dev/tty' no longer interpreted as
- `echo hi 1> /dev/tty' (is `echo hi 1abc123 > /dev/tty')
- - `echo hi 1<> /tmp/does-not-exist' now works (used to say cannot
- open)
- - c_sh.c(c_umask): umask now takes symbolic arguments (g-r, +w, etc.)
- - c_ksh.c(c_whence): pass flag[FTRACKALL] to findcom() instead of 1.
- - `echo hi >< bar' now produces an error
- - jobs.c(j_lookup): now checks for ambiguous job specifications;
- callers now get an error message.
- - c_ksh.c(c_fgbg): multiple jobs can be specified
- - emacs.c(x_transpose): move past transposed chars like (gnu) emacs
- does
- - main.c(main): don't copy initcoms (messes up memory allocated for
- shf_iob[] in initio(), should not be necessary)
- - main.c(main), var.c(import), var.c(typeset), c_ksh.c(c_alias),
- expr.c(token), misc.c(strnsave): added strnsave() function; use it
- instead of writing nulls in the middle of strings; main() no longer
- copies startup commands before executing them.
- - vi.c: wbuf[] no longer a fixed size (was hard coded to 80 chars).
- - alloc.c(aresize): if passed a null pointer, don't free it
- - expand.h: restored usage description and NOTE from previous version
- - alloc.c, table.h, table.c:
- - changed struct fields named `free' to nfree (struct table) and
- freelist (struct Block) to allow memory debugging
- (involves #defining free)
- - main.c(main): smart initialization of PWD (ensures it is always
- valid).
- - lex.h, table.h, tree.h: removed redundent function declarations
- (were also in proto.h)
- - sh.h: increased LINE from 256 to 1024
- - main.c(include), sh.h(E_INC), c_sh.c(c_return): added hack so a
- return in a included file returns to the includer instead of
- exiting the shell. Very useful in $ENV scripts and profiles,
- eg, so the whole script does not have to be parsed for
- non-interactive shells.
- This is not compatible with the at&t ksh, whose man page says
- return is the same as exit outside of functions. May be modified
- in the future. (note that at&t ksh parses a .'ed file before
- executing anything, so a premature return would not speed its
- parsing, which is why the return hack was added to pdksh)
- - exec.c(iosetup): don't save fd if already saved (and don't
- generate an error)
- - exec.c(findcom): in if (..ALLOC && eaccess), test for
- ALLOC redundent - always call afree()
diff --git a/bin/pdksh/IAFA-PACKAGE b/bin/pdksh/IAFA-PACKAGE
deleted file mode 100644
index 879682c0a61..00000000000
--- a/bin/pdksh/IAFA-PACKAGE
+++ /dev/null
@@ -1,17 +0,0 @@
-$OpenBSD: IAFA-PACKAGE,v 1.5 1996/11/21 07:59:25 downsj Exp $
-
-Title: pdksh
-Version: 5.2.12
-Description: A public domain implementation of the Korn shell (ksh88),
- a UNIX command line interpreter / scripting language; the few
- missing ksh features are being added and the shell is being
- POSIXized.
-Author: (Eric Gisin), (Charles Forsyth), (John R MacMillan),
- sjg@zen.void.oz.au (Simon J. Gerraty),
- michael@cs.mun.ca (Michael Rendell), (plus many others)
-Maintained-by: michael@cs.mun.ca (Michael Rendell)
-Maintained-at: ftp://ftp.cs.mun.ca:/pub/pdksh/
-Platforms: Written in C, runs on most UNIX boxes (uses GNU autoconf;
- works best in a POSIX or BSD environment). Also runs on OS/2.
-Copying-Policy: Freely Redistributable (mostly public domain, some copyrighted)
-Keywords: pdksh, ksh, Korn, shell, command line interpreter
diff --git a/bin/pdksh/INSTALL b/bin/pdksh/INSTALL
deleted file mode 100644
index afd11fa04cb..00000000000
--- a/bin/pdksh/INSTALL
+++ /dev/null
@@ -1,151 +0,0 @@
-$OpenBSD: INSTALL,v 1.1 1996/08/14 06:19:10 downsj Exp $
-
-[This file is the generic GNU autoconf/configure installation description,
- see the README for pdksh specific configuration/installation information]
-
- This is a generic INSTALL file for utilities distributions.
-If this package does not come with, e.g., installable documentation or
-data files, please ignore the references to them below.
-
- The `configure' shell script attempts to guess correct values for
-various system-dependent variables used during compilation, and
-creates the Makefile(s) (one in each subdirectory of the source
-directory). In some packages it creates a C header file containing
-system-dependent definitions. It also creates a file `config.status'
-that you can run in the future to recreate the current configuration.
-
-To compile this package:
-
-1. Configure the package for your system.
-
- Normally, you just `cd' to the directory containing the package's
-source code and type `./configure'. If you're using `csh' on an old
-version of System V, you might need to type `sh configure' instead to
-prevent `csh' from trying to execute `configure' itself.
-
- Running `configure' takes awhile. While it is running, it
-prints some messages that tell what it is doing. If you don't want to
-see any messages, run `configure' with its standard output redirected
-to `/dev/null'; for example, `./configure >/dev/null'.
-
- To compile the package in a different directory from the one
-containing the source code, you must use a version of `make' that
-supports the `VPATH' variable, such as GNU `make'. `cd' to the
-directory where you want the object files and executables to go and run
-the `configure' script. `configure' automatically checks for the
-source code in the directory that `configure' is in and in `..'. If
-for some reason `configure' is not in the source code directory that
-you are configuring, then it will report that it can't find the source
-code. In that case, run `configure' with the option `--srcdir=DIR',
-where DIR is the directory that contains the source code.
-
- By default, `make install' will install the package's files in
-`/usr/local/bin', `/usr/local/man', etc. You can specify an
-installation prefix other than `/usr/local' by giving `configure' the
-option `--prefix=PATH'. Alternately, you can do so by consistently
-giving a value for the `prefix' variable when you run `make', e.g.,
- make prefix=/usr/gnu
- make prefix=/usr/gnu install
-
- You can specify separate installation prefixes for
-architecture-specific files and architecture-independent files. If you
-give `configure' the option `--exec-prefix=PATH' or set the `make'
-variable `exec_prefix' to PATH, the package will use PATH as the prefix
-for installing programs and libraries. Data files and documentation
-will still use the regular prefix. Normally, all files are installed
-using the same prefix.
-
- Some packages pay attention to `--with-PACKAGE' options to
-`configure', where PACKAGE is something like `gnu-as' or `x' (for the
-X Window System). They may also pay attention to `--enable-FEATURE'
-options, where FEATURE indicates an optional part of the package. The
-README should mention any `--with-' and `--enable-' options that the
-package recognizes.
-
- `configure' also recognizes the following options:
-
-`--help'
- Print a summary of the options to `configure', and exit.
-
-`--quiet'
-`--silent'
- Do not print messages saying which checks are being made.
-
-`--verbose'
- Print the results of the checks.
-
-`--version'
- Print the version of Autoconf used to generate the `configure'
- script, and exit.
-
-`--x-includes=DIR'
- X include files are in DIR.
-
-`--x-libraries=DIR'
- X library files are in DIR.
-
- `configure' also accepts and ignores some other options.
-
- On systems that require unusual options for compilation or linking
-that the package's `configure' script does not know about, you can give
-`configure' initial values for variables by setting them in the
-environment. In Bourne-compatible shells, you can do that on the
-command line like this:
-
- CC='gcc -traditional' LIBS=-lposix ./configure
-
-On systems that have the `env' program, you can do it like this:
-
- env CC='gcc -traditional' LIBS=-lposix ./configure
-
- Here are the `make' variables that you might want to override with
-environment variables when running `configure'.
-
- For these variables, any value given in the environment overrides the
-value that `configure' would choose:
-
- - Variable: CC
- C compiler program. The default is `cc'.
-
- - Variable: INSTALL
- Program to use to install files. The default is `install' if you
- have it, `cp' otherwise.
-
- For these variables, any value given in the environment is added to
-the value that `configure' chooses:
-
- - Variable: DEFS
- Configuration options, in the form `-Dfoo -Dbar...'. Do not use
- this variable in packages that create a configuration header file.
-
- - Variable: LIBS
- Libraries to link with, in the form `-lfoo -lbar...'.
-
- If you need to do unusual things to compile the package, we encourage
-you to figure out how `configure' could check whether to do them, and
-mail diffs or instructions to the address given in the README so we
-can include them in the next release.
-
-2. Type `make' to compile the package. If you want, you can override
-the `make' variables CFLAGS and LDFLAGS like this:
-
- make CFLAGS=-O2 LDFLAGS=-s
-
-3. If the package comes with self-tests and you want to run them,
-type `make check'. If you're not sure whether there are any, try it;
-if `make' responds with something like
- make: *** No way to make target `check'. Stop.
-then the package does not come with self-tests.
-
-4. Type `make install' to install programs, data files, and
-documentation.
-
-5. You can remove the program binaries and object files from the
-source directory by typing `make clean'. To also remove the
-Makefile(s), the header file containing system-dependent definitions
-(if the package uses one), and `config.status' (all the files that
-`configure' created), type `make distclean'.
-
- The file `configure.in' is used to create `configure' by a program
-called `autoconf'. You only need it if you want to regenerate
-`configure' using a newer version of `autoconf'.
diff --git a/bin/pdksh/LEGAL b/bin/pdksh/LEGAL
deleted file mode 100644
index 78dd76f95dc..00000000000
--- a/bin/pdksh/LEGAL
+++ /dev/null
@@ -1,36 +0,0 @@
-$OpenBSD: LEGAL,v 1.1 1996/08/14 06:19:10 downsj Exp $
-
-pdksh is provided AS IS, with NO WARRANTY, either expressed or implied.
-
-The vast majority of the code that makes pdksh is in the public domain.
-The exceptions are:
- sigact.c and sigact.h
- These are covered by copyrighten by Simon J. Gerraty;
- the copyright notice for these files is as follows:
- This is free software. It comes with NO WARRANTY.
- Permission to use, modify and distribute this source code
- is granted subject to the following conditions.
- 1/ that that the above copyright notice and this notice
- are preserved in all copies and that due credit be given
- to the author.
- 2/ that any changes to this code are clearly commented
- as such so that the author does get blamed for bugs
- other than his own.
- aclocal.m4
- This is covered by the GNU General Public Licence (GPL)
- as it contains modified versions of macros that come with
- GNU autoconf. As this is used solely for configuration,
- the pdksh code itself is not covered by the GPL.
- The following is taken from autoconf 2.x documentation
- (info autoconf questions distributing) concerning use
- of autoconf in programs:
-
- There are no restrictions on how the configuration
- scripts that Autoconf produces may be distributed
- or used. In Autoconf version 1, they were covered by
- the GNU General Public License. We still encourage
- software authors to distribute their work under terms
- like those of the GPL, but doing so is not required
- to use Autoconf.
-
-That's it. Short and simple.
diff --git a/bin/pdksh/Makefile b/bin/pdksh/Makefile
deleted file mode 100644
index 85145ad30ed..00000000000
--- a/bin/pdksh/Makefile
+++ /dev/null
@@ -1,30 +0,0 @@
-# $OpenBSD: Makefile,v 1.8 1996/11/30 23:54:36 downsj Exp $
-
-PROG= ksh
-SRCS= alloc.c c_ksh.c c_sh.c c_test.c c_ulimit.c edit.c emacs.c \
- eval.c exec.c expr.c history.c io.c jobs.c lex.c mail.c \
- main.c misc.c missing.c path.c shf.c syn.c table.c trap.c \
- tree.c tty.c var.c version.c vi.c
-
-DEFS= -DHAVE_CONFIG_H
-CFLAGS+=${DEFS} -I. -I${.CURDIR} -DKSH
-MAN= ksh.1 sh.1
-
-CLEANFILES+= siglist.out emacs.out
-
-LINKS= ${BINDIR}/ksh ${BINDIR}/rksh
-LINKS+= ${BINDIR}/ksh ${BINDIR}/sh
-MLINKS= ksh.1 rksh.1
-
-.depend trap.o: siglist.out
-.depend emacs.o: emacs.out
-
-siglist.out: config.h sh.h siglist.in siglist.sh
- /bin/sh ${.CURDIR}/siglist.sh \
- "${CPP} ${CPPFLAGS} ${DEFS} -I${.CURDIR}" \
- < ${.CURDIR}/siglist.in > siglist.out
-
-emacs.out: emacs.c
- /bin/sh ${.CURDIR}/emacs-gen.sh ${.CURDIR}/emacs.c > emacs.out
-
-.include <bsd.prog.mk>
diff --git a/bin/pdksh/NEWS b/bin/pdksh/NEWS
deleted file mode 100644
index f1115015719..00000000000
--- a/bin/pdksh/NEWS
+++ /dev/null
@@ -1,603 +0,0 @@
-$OpenBSD: NEWS,v 1.5 1996/11/21 07:59:26 downsj Exp $
-
-Version 5.2.12
-
-* bug fixes
- * editing: shell recognizes window resizes on Dec alphas (config problem).
- * alias: no longer dumps core if alias is in a command substitution.
- * alias: everything after ;\n or \n\n was ignored in aliases.
- * exec: temp files used by here docs in functions now cleaned up on exec.
- * possible core dump when cleaning up environment fixed.
- * vi: set -o vi-show8 now does what it was supposed to do (cat -v like).
- * job control: process group synchronization (needed on systems with
- broken setpgrp()) now works when the pipeline contains built in commands.
- * vi: if set -o vi-tabcomplete, tab works in command mode as well.
- * set/typeset: unset parameters are only reported if they have attributes.
-
-
-Version 5.2.11
-
-* bug fixes
- * aliases: expansion was reading an extra character (bug added in 5.2.10).
-
-
-Version 5.2.10
-
-* bug fixes
- * parsing: handling of backslash-newline fixed (esp. in here documents).
- * read: prints prompt if non-interactive and input is a tty.
-
-
-Version 5.2.9
-
-* bug fixes
- * config: using LDSTATIC no longer generates config error.
- * config: can compile as sh again (--enable-shell=sh).
- * config: should compile on machines with broken "gcc -g"
- * config: fixed test for broken S_IFIFO.
- * config: fixed test for getwd() routine.
- * config: better NeXT support (signal list generated correctly, clock_t
- type detected, enable job control in rlogin sessions)
- * parsing: assignments containing brackets ([]) not treated as commands.
- * editing: terminal column width determined correctly on startup.
- * vi: long prompts truncated (more or less) correctly.
- * file completion: files of the form ~user (no /'s) expanded correctly.
-
-* at&t ksh method for delimiting hidden characters in prompt added (i.e.,
- start prompt with non-printing char and \r, use char to delimit esc codes).
-
-
-Version 5.2.8
-
-* bug fixes
- * configuration: handle FreeBSD's strange S_ISSOCK.
- * test: added == operator.
- * configuration: fixed opendir/dirent usage.
- * redirections before subshells handled correctly.
- * COLUMNS/LINES are no longer exported when they are automatically set.
- * mail checks and PS1/PS4 expansions removed if compiled as sh.
- * subcommands in PS1 no longer generate bogus warning messages.
- * environment variables not longer messed up on 16-bit machines.
- * unset: now returns non-zero if variable/function isn't set.
- * select: only prints menu first time, if REPLY is null or on blank line.
- * check for `cannot execute' improved, error message says why.
- * typeset: now reports variables with attributes but now value.
- * vi/emacs file completion: does directory listing on zero length names.
- * arithmetic: non-numeric parameters expanded recursively.
- * arithmetic: identifiers in unevaluated part of ?:,&&,|| parsed correctly.
- * functions: unsetting a function within itself is now safe.
- * arrays: unsetting element 0 of an array no longer kills the whole array.
- * co-processes now behave like ksh93 co-processes (and less like ksh88).
-
-* functions declared with "function foo" are treated differently (from those
- declared with "foo()"): $0 is (not) set to the function name, assignments
- before function calls aren't (are) kept in the parent shell.
-
-* vi: added vi-esccomplete option for people who want ESC-ESC completion.
-
-* vi/emacs: now notice window size changes (but not while editing a line).
-
-* emacs: <esc># now does the comment/uncomment thing.
-
-* arithmetic: ++, -- and , added.
-
-
-Version 5.2.7
-
-* bug fixes
- * vi: commands can be longer that 16 chars...
-
-
-Version 5.2.6
-
-* bug fixes
- * break/continue: if too big a number is given, last enclosing loop is used.
- * set: set +o now generates a set command that can be saved and executed.
- * COLUMNS/LINES are now exported when they are automatically set.
- * emacs: completion: space not added after directory names.
- * vi: # command inserts # after each newline; # on commented line
- undoes the commenting.
- * some regression tests made less sensitive to their environment.
- * should compile on os/2 again.
-
-
-Version 5.2.5
-
-* bug fixes
- * configuration: if sig_setjmp() being used, use sigjmp_buf.
- * configuration: test for times() fixed.
- * configuration: ANSI usage of setjmp() and offsetof().
- * echo/print: octal number in \ sequence must start with a 0.
- * echo: don't treat a lone minus as an option.
- * typeset -f: correctly prints functions with select statements.
- * vi: / with no pattern repeats last search.
- * vi: repeat counts no longer effect file completion/expansion.
- * vi: tab-completion now also works in command mode.
- * emacs/vi: ^O key now read as ^O on suns/alphas (was eaten by tty driver).
- * emacs: now has file expansion (^[*).
- * emacs: ^O goes to next command, not next next command.
- * COLUMNS/LINES: environment variables now set on start up.
- * variables: command line assignments can't change readonly variables.
- * arithmetic: giving multiple bases (5#4#3) no longer allowed.
- * arithmetic: when assigning a non-integer variables, base no longer shown.
- * history: fixed replacement bug introduced in last release.
- * history: -1 refers to the previous command, not current fc command.
- * parsing: correctly handles command substitutions starting with a newline.
-
-* full command completion added (both vi and emacs).
-
-
-Version 5.2.4
-
-* bug fixes
- * PS1 imported from environment again.
- * vi handles prompts with embedded newlines.
- * errors redirecting stderr aren't lost.
- * redirection errors for <&n no longer reported as to >&n.
- * don't do globbing on re-direction targets if not interactive (POSIX).
- * pattern matching in [[ foo = foo*bar ]] now works again.
- * HUP signals are passed on to jobs running in the foreground.
- * $? now valid (ie, not 0) in trap handlers, `...` expressions, etc.
- * noclobber doesn't effect redirections to non-regular files (eg, /dev/null)
- * \newline in here-document delimiters handled correctly.
- * typeset -f now reports unloaded autoload functions properly.
- * ~,~+,~- are not expanded if HOME,PWD,OLDPWD are unset.
- * vi completion/expansion: * not appeded if word contains $.
- * cd: error message contains correct directory string.
- * vi expansion list: printed in column form ala at&t ksh.
- * ^C while reading .profile/$ENV nolonger causes shell to exit.
- * option errors for build-in commands now include command name.
- * emacs completion/expansion: ' and " are treated as word delimiters.
- * fc: replacements (a=b) no longer truncates the command.
- * alias: alias -t -r now cleans out the tracked alias table.
-
-* compile-time configuration changed: configure script --enable-XXX options
- replace the old options.h file. Use "configure --help" for information
- on what the options do (they are basicly the same as what was in the
- options.h file). Shell can be configured as a (almost) plain bourne
- shell using the --enable-shell=sh (also generates appropriate man page).
- Installed name of program (ksh or sh) can be modified using configure's
- --program-* options.
-
-* ulimit: added -p (maxproc) option.
-
-* case statements can use the old syntax of {,} instead of in,esac.
-
-* extended file globbing added (eg, f*(bar|Bar) matches f, fbar fBarbar, etc).
-
-* trim expressions can be of the form ${parameter#pattern1|pattern2|...}.
-
-* if compiled as sh, $ENV included only if posix option is set.
-
-* vi: U command added (undo all changes on line).
-
-* the Bugs script has been replaced by a new regression testing system, kept
- in the tests/ directory (contains a perl script which sets up a test
- environment and runs tests, and a bunch of tests).
-
-
-Version 5.2.3
-
-* bug fixes
- * arrays: set -A and unset now unset whole array.
- * history(complex version): fixed core caused by uninitialized hist_source.
- * getopts: will continue parsing options if called after error.
- * getopts: doesn't print shell name twice in error message.
- * posix: if posix option is set, $0 is always the name of the shell.
- * history: "fc -s foo" now finds foo if it is the most recent command.
- * let: expression errors no longer cause scripts to exit.
- * PS1: does not go into infinite loop if there is an expansion error.
- * configure: memmove/bcopy test has a change of working now.
- * configure: check for flock(), undefine COMPLEX_HISTORY if not found.
- * substitution: tilde substitution works in word part of ${var[-+=?]word}.
- * history: "fc <number>" now edits <number>, not <number> to most recent.
- * cd: two argument form works again.
- * special commands taking assignments (alias,set,etc.): field splitting,
- file globbing, etc. suppressed only for args that look like assignments.
- * command: -V now finds reserved words.
-
-* added support for Korn's /dev/fd tests
-
-* new compile time option: DEFAULT_ENV - if defined, it names a file to
- include if $ENV is not set.
-
-* test -o option: if option starts with a !, the test is negated. The test
- always fails if the option doesn't exist (so [ -o foo -o -o !foo ] is true
- iff option foo exists).
-
-* new option: set -o nohup (currently on by default) - if set, running jobs
- are not kill -HUP'd when a login shell exits; if clear, they are. In
- future, this will be clear by default (to act like at&t ksh) - if you don't
- (won't) like this, add "[ -o !nohup ] && set -o nohup" to your .profile.
-
-Version 5.2.2
-
-* bug fixes
- * included c_test.h in distribution (opps).
-
-Version 5.2.1
-
-* bug fixes
- * emacs: buffer no longer overflowed when completing file names/commands.
- * emacs: <ESC><tty-erase-char> now bound to delete-back-word (was ...-char).
- * emacs: ignores a space char after ^V (version), as in at&t ksh.
- * emacs: ^O bound to newline-and-next, ^X^Y bound to list-file.
- * emacs: emacs words now include underscore.
- * vi: set -o markdirs, directories and ^[= now get along.
- * cd: -P no longer leaves .. and . in PWD.
- * cd: if CDPATH set and can't cd, error doesn't contain any of CDPATH.
- * cd: sets PWD properly, on machines without getwd().
- * configuration: unistd.h test fixed (include sys/types before dirent.h).
- * configuration: detects memmove/bcopy's that don't handle overlaps.
- * [[ ... ]] does lazy evaluation (eg, [[ ! -f foo || $(<foo) = bar ]] does
- not evaluate $(<foo) if foo doesn't exist).
-
-
-Version 5.2.0
-
-* bug fixes
- * vi: completion now allows globbing characters.
- * vi: can deal with very long prompts.
- * vi: . (redo) works after j, k, return.
- * vi: [dyc]% causing backwards motion now gets correct start/end position.
- * vi: complete_word (<ESC>\) no longer rings bell on ambiguous matches.
- * vi: globbing doesn't append * if last component of file has globbing chars.
- * emacs: most commands now take arguments, arguments can be multi digit.
- * emacs: newline-and-next command works more correctly.
- * after set -u, trimming substitutions no longer automatically fail.
- * set -i no longer reports an internal error.
- * FPATH: no longer incorrectly complains about function not being defined.
- by a file; when it connectly complains, shell name in error is correct.
- * set -a; set -o allexport: these now do something.
- * shell deals with non-blocking input (clears non-blocking flag).
- * autoconf: fixed memmove/memcpy tests.
- * ! translation in prompt now done before parameter substitution.
- * siglist.sh works around bug in bash 1.4.3.
- * correct positional parameters accessible in local assignments.
- * (sleep 100&) no longer waits for sleep to complete.
-
-* fc -s option added (same as -e -).
-
-* vi: ^V command (version) added.
-
-* vi: @<char> macros added (@X executes vi commands in alias _X).
-
-* emacs: bind -l lists all command names.
-
-* emacs: goto-history command added.
-
-* emacs: search-char function changed to search-char-forward;
- added search-char-backward (bound to <ESC>^]).
-
-* cd and pwd take -L and -P options; added set -o physical option
- (PWD,OLDPWD no longer readonly).
-
-* new command line -l option tells shell it is a login session.
-
-* os2 changes completed.
-
-* uses autoconf 2.x (was using 1.x).
-
-Version 5.1.3
-
-* bug fixes
- * fixed bug in arithmetic expression evaluation (||,&& caused core dump).
- * ulimit code now uses rlim_t or quad_t, if appropriate.
- * vi: file completion in command mode of single character filename works.
- * vi: file completion with markdirs set resulted in two trailing /'s.
- * vi: completion/expansion/listing acts like at&t ksh when expand fails.
- * vi: ~ takes count.
- * lines from history file are no longer negative (easy history).
- * Makefile now uses manual extension consistently.
- * fc now allows out of range relative (negative) numbers.
- * functions with elif now printed correctly.
- * FPATH now searched if PATH search fails, as in at&t ksh.
-
-* typeset -f output is readable (and more correct)
-
-* compiles under SCO unix
-
-* more os/2 changes integrated
-
-Version 5.1.2
-
-* bug fixes
- * for i; do ...; done now accepted.
- * leading non-white-space IFS chars no longer ignored (now delimit fields).
- * fixed globbing code so echo /usr/*/make works.
-
-Version 5.1.1
-
-* bug fixes
- * { ..;} allowed instead of do ..;done in for/select loops
- * EOF after ; or & no longer causes syntax error
- * complex history: when shrinking history file, keeps inside buffer space.
- * vi editing: `v' on modified line no longer changes command numbering.
- * ^C in vi/emacs no longer prints two newlines.
- * long arguments (> 255) with globbing characters don't cause core dumps.
-
-* new (un)option, KSH, which compiles out ksh code (for producing minimal sh).
-
-* os/2 changes partly merged.
-
-Version 5.1.0
-
-* bug fixes
- * problem caused by _POSIX_VDISABLE on BSDI machines fixed
- * exit status set to 127 if command file could not be opened
- * profile files processed if basename argv[0] starts with (was $0)
- * PWD now imported properly from environment.
- * emacs code now either uses dynamic buffers or does overflow checking.
- * emacs forward-word and delete-forward-word now work like other emacs's.
- * ^C/^\ in vi/emacs work like at&t ksh (prompt reprinted, even if trapped).
- * history number to command mapping now constant (numbers used to change).
- * configuration: BSD tty now used on ultrix (avoids type ahead problem)
- * eof in the middle of multiline commands now ignored if ignoreeof set.
- * vi space command now works again.
- * pointer mismatch compiler warning for waitpid() call dealt with.
- * emacs internal memory error in command completion fixed.
- * autoloaded functions now work first try.
- * SECONDS parameter now acts like in at&t ksh.
-
-* sense of vi-show8 option changed: 8-bit characters are printed as is by
- default; turning on vi-show8 now causes chars with 8th bit set to be
- prefixed with M-.
-
-* missing sections in man page added (now basicly complete)
-
-* emacs ^V command added: prints ksh version
-
-* vi g command added: moves to most recent history
-
-Version 5.0.10
-
-* bug fixes
- * [[ ]] construct unbroken.
- * the newline after a here document marker is now read properly.
- * blank lines no longer cause $? to be set to 0.
- * mail checking now uses atime/mtime instead of size.
- * changing attributes of exported parameters no longer causes core dump.
- * the last command in a file does not have to end in a newline.
- * empty expressions now treated as 0 (previously generated an error).
- * nul bytes stripped from input.
- * 0241 (M-!) in a command substitution no longer lost.
- * when read used in startup file, line continuation no longer causes crash.
- * very long commands in history no longer cause vi to overwrite memory.
- * easy history: when saving history, avoid going past the end of history.
- * emacs mode no longer entered if EDITOR/VISUAL set to null string.
- * command -p disabled in restricted mode.
- * closed file descriptors are re-closed after a redirection.
- * lone [ (test command) no longer causes globbing code to search directory.
- * if TIMES_BROKEN is defined, ksh_times no longer recurses infinitely.
- * `r r' no longer repeats r command forever.
- * make depend no longer generates backslash followed by a blank line.
- * globbing code now deals with symlinks that point to non-existent files.
- * if the ] is missing in a pattern, the [ matches the [ character.
- * syntax errors in test no longer have two newlines.
- * in vi, G now goes to the oldest history (was newest).
- * configuration: test for sys_siglist now harder for optimizers to break.
- * configuration: look for clock_t in sys/times.h.
- * configuration: use _SIGMAX, if available, for # of signals.
- * SIGHUP now causes builtin read command to exit.
- * wait builtin now returns whenever a traped signal occurs as per POSIX.
-
-* v command now works in vi; anchored searches now work in vi mode (/^ptrn);
- multi-line commands displayed correctly by history.
-
-* echo is now schizophrenic: accepts -n/-e/-E and backslash sequences.
-
-* test -H file added (checks for context dependent files on HPs).
-
-* set -o gmacs and markdirs honoured.
-
-* ansi arrow keys in default emacs key bindings.
-
-* ulimit now takes arithmetic expression (as per Korn book).
-
-* co-processes changed to be more compatible with at&t ksh.
-
-Version 5.0.9
-
-* bug fixes
- * FOO is put in the environment for FOO=bar exec blah.
- * compiles under QNX and with dmake.
- * the file pattern [!a--]* is now invalid (POSIX) (used to match everything)
- * echo "${foo:-"a"}*" no longer the same as echo a*.
- * alternation (brace expansion) fixes:
- * brace expansion done after variable expansion, as in csh/at&t ksh.
- * `echo a{b,c' no longer gives "Missing }" error (it echos a{b,c).
- * expansion only done if there is a comma (ie, `echo {a}' prints {a}).
- * globbing/expansion code passes 0x80 unharmed.
- * "echo ${XX=a*b}" no longer sets XX to "a\200*b".
- * "echo ${unset-a*b}" no longer has \200 in the error message.
- * bad substitution error generated for things like ${x:a}, ${x^a}, etc.
- * `x="a cdef"; echo ${x#a c}' now prints "def" instead of "a a cdef".
- * on systems where /etc/passwd//// is a valid name, echo /etc/pass*/ no
- longer matches /etc/passwd.
- * trace output (set -x) flushed correctly, PS4 initialized.
- * ulimit output ungarbled, code to use {set,get}ulimit (if available)
- enabled.
- * tilde expansion done in word part of ${foo-~/bar}
- * when reading stdin (ie, ksh -s), no longer reads too much.
- * shell handles i/o redirection and errors in builtin commands as per
- POSIX (still have to sort out variable assignment errors).
- * starting jobs that save/change/restore tty settings in the background
- no longer messes up tty settings when job finishes.
- * the pattern [a'-'z] now matches three characters, not 26, and
- the pattern [ab']'] also matches three characters.
-
-* a mostly complete man page! (work is still in progress)
-
-* quoting inside $(..) mostly works.
-
-* error reporting has been orthogonalized.
-
-* brace expansion on by default (can be disabled with set +o braceexpand, or
- set -o posix).
-
-* output of "set -o" now fits on a normal screen.
-
-* co-processes added (|&, read -p, print -p, etc.).
-
-* restricted mode added (for what its worth).
-
-* vi now prints meta characters with M- prefix, unless vi-show8 option is on.
-
-Version 5.0.8
-
-* bug fixes
- * two problems in fc (introduced in 5.0.7)
- * install target in Makefile missing a dollar
-
-Version 5.0.7
-
-* POSIX command command added
-
-* a few bug fixes
- * now compiles with various options undefined (eg, VI, EMACS, JOBS).
- * fixed typos in Makefile.in (maxext -> manext) and ksh.1 (\f -> \fP).
- * CLK_TCK defined to correct value for FreeBSD 1.1.5 (and earlier?).
- * original process group restored when an exec is done.
- * the exit value of set is that of the last $(...) on the command line.
- * ditto for a command with no command (eg, x=`false`).
- * command variable assignments done before path search (so PATH=... x works)
- and are added as they are processed (so A=1 B=$A works).
- * variable assignments infront of function calls are exported to programs
- inside the function.
- * aliases with trailing space are only honoured in command contexts
- if in posix mode.
-
-* make depend target added; install target warns if ksh not in /etc/shells.
-
-* set -o bgnice now does something.
-
-* vi mode: ESC is no longer a file completion command (too annoying).
-
-Version 5.0.6
-
-* most reported bugs/problems fixed (all but two).
-
-* temporary files now created in $TMPDIR (if it is a sane path).
-
-Version 5.0.5
-
-* function parsing POSIXized (function bodies can be any compound command,
- redirections after functions effect function invocation, not the
- instantiation, the () in a function definition now parsed as two tokens).
-
-* exit bultin now does stopped jobs check.
-
-* set -p/-o priviliged supported.
-
-* test builtin now believed to be completely posix.
-
-* a default path is now used when PATH is not set (defined in options.h).
-
-Version 5.0.4
-
-* configuration checks for buggy opendir()s and setpgrp()s.
-
-* autoloading functions now supported.
-
-* functions can safely redefine themselves.
-
-Version 5.0.3
-
-* hash command changed to "alias -t"; whence -p added; print -s added
- (all as in at&t ksh); unalias -a added (POSIX).
-
-* test builtin POSIX complient
-
-* TMOUT parameter supported (at&t ksh: timeout interactive shells)
-
-Version 5.0.2
-
-* trap/error handling changed to eliminate longjmp()s from signal handlers;
- trap ERR added.
-
-* ksh conditional expressions ([[ .. ]]) supported.
-
-* arithmetic expressions (let, $((..)), etc.) now understand full C
- integer expressions (except ++/-- and sizeof()).
-
-* typeset -L -R -Z -u -l added (as in at&t ksh)
-
-* at&t/posix $(( .. )) arithmetic expansions supported.
-
-Version 5.0.1
-
-* set -e no longer effects commands executed as part of if/while/until/&&/||/!
- condition.
-
-* posix ! keyword now recognized.
-
-* posix getopts; if not in posix mode, getopts will accept options starting
- with + (at&t kshism)
-
-* syntax error messages improved (says what was unexpected/unmatched)
-
-Version 4.9+mun.5
-
-* all known bugs related to job control fixed:
- * fg,bg,jobs,wait,kill commands fully POSIX complient
- * signals are no longer reported for foreground jobs killed by SIGINT and
- SIGPIPE
- * pipeline process groups now created more reliablely (was a problem
- if first process exited before second process exec'd).
- * "(: ; cat /etc/termcap) | sleep" nolonger hangs
-
-* save/restore tty mode if command succeeds/fails, respectively. Edit
- mode (emacs,vi) no longer use old tty mode information
-
-* test command: added -h
-
-* alternations option renamed to braceexpand (eg, use set -o braceexpand).
- Old usage (set -o alternations) still accepted (will disappear in next
- version).
-
-* trap/kill now accept upper and lower case signal names.
-
-Version 4.9+mun.3
-
-* here documents in functions now work properly
-
-* read command: added -s option, use REPLY if no variable specified
-
-* don't accept "while command; done" as a valid command
-
-* fg,bg,jobs,wait,kill commands mostly POSIX complient.
-
-* unset command: added POSIX -v option
-
-* set command: added -A option
-
-* handle ${array[@]} and ${array[*]}
-
-* compiles with old bsd 4.2 compiler (pcc)
-
-* new versions of etc/profile and etc/ksh.profile
-
-Version 4.9+mun.2 (versus 4.9)
-
-* directory/file structure has been re-arranged:
- * moved files from sh directory up a level, deleted sh directory
- * created misc directory, old ChangeLog,README,.. files moved to misc
-
-* now uses GNU autoconf for compilation.
-
-* no longer uses stdio FILE *'s for I/O redirection (most stdio
- usage has been removed). Solves many porting problems caused by
- dup'd file descriptors, forked processes and exiting.
-
-* removed lint from code (compiles with very few warning with gcc -O -Wall
- -Wno-comment)
-
-* has array support (needs work but is pretty functional).
-
-* ulimit command now more functional on more machines. Compatable with at&t ksh.
-
-* command line and set option parsing cleaned up, POSIXized.
-
-* POSIX IFS handling.
-
-* many many small bug fixes (see ChangeLog)
diff --git a/bin/pdksh/NOTES b/bin/pdksh/NOTES
deleted file mode 100644
index 17f29108eda..00000000000
--- a/bin/pdksh/NOTES
+++ /dev/null
@@ -1,514 +0,0 @@
-$OpenBSD: NOTES,v 1.3 1996/10/01 02:05:29 downsj Exp $
-
-General features of at&t ksh that are not (yet) in pdksh:
- - exported aliases.
- - exported functions.
- - set -t.
- - signals/traps not cleared during functions.
- - trap DEBUG, local ERR and EXIT traps in functions.
- - ERRNO, LINENO parameters.
- - doesn't have posix file globbing (eg, [[:alpha:]], etc.).
- - use of an `agent' to execute unreadable/setuid/setgid shell scripts
- (don't ask).
- - read/select aren't hooked in to the the command line editor
- - the last command of a pipeline is not run in the parent shell
-
-Known bugs (see also BUG-REPORTS and PROJECTS files):
- Variable parsing, Expansion:
- - some specials behave differently when unset (eg, IFS behaves like
- " \t\n") others lose their special meaning. IFS/PATH taken care of,
- still need to sort out some others (eg, TMOUT).
- Parsing,Lexing:
- - line numbers in errors are wrong for nested construct. Need to
- keep track of the line a command started on (can use for LINENO
- parameter as well).
- - a $(..) expression nested inside double quotes inside another $(..)
- isn't parsed correctly (eg, $(echo "foo$(echo ")")") )
- Commands,Execution:
- - setting special parameters that have side effects when
- changed/restored (ie, HISTFILE, OPTIND, RANDOM) in front
- of a command (eg, HISTFILE=/foo/bar echo hi) effects the parent
- shell. Note that setting other (not so special) parameters
- does not effect the parent shell.
- - `echo hi | exec cat -n' causes at&t to exit, `exec echo hi | cat -n'
- does not. pdksh exits for neither. Don't think POSIX requires
- an exit, but not sure.
- - `echo foo | read bar; echo $bar' prints foo in at&t ksh, nothing
- in pdksh (ie, the read is done in a seperate process in pdksh).
- Misc:
-
-Known differences between pdksh & at&t ksh (that may change)
- - vi:
- - `^U': at&t: kills only what has been inserted, pdksh: kills to
- start of line
- - at&t ksh login shells say "Warning: you have running jobs" if you
- try to exit when there are running jobs. An immediate second attempt
- to exit will kill the jobs and exit. pdksh does not print a warning,
- nor does it kill running jobs when it exits (it does warn/kill for
- stopped jobs).
- - TMOUT: at&t prints warning, then waits another 60 seconds. If on screwed
- up serial line, the output could cause more input, so pdksh just
- prints a message and exits. (Also, in at&t ksh, setting TMOUT has no
- effect after the sequence "TMOUT=60; unset TMOUT", which could be
- useful - pdksh may do this in the future).
- - in pdksh, if the last command of a pipeline is a shell builtin, it is
- not executed in the parent shell, so "echo a b | read foo bar" does not
- set foo and bar in the parent shell (at&t ksh will).
- This may get fixed in the future, but it may take a while.
- - in pdksh, set +o lists the options that are currently set, in at&t ksh
- it is the same as set -o.
- - in pdksh emacs mode, ^T does what gnu emacs does, not what at&t ksh
- does.
- - in ksh93, `. name' calls a function (defined with function) with POSIX
- semantics (instead of ksh semantics). in pdksh, . does not call
- functions.
- - test: "test -f foo bar blah" is the same as "test -f foo" (the extra
- arguments, of which there must be at least 2, are ignored) - pdksh
- generates an error message (unexpected operator/operand "bar") as it
- should. Sometimes used to test file globs (e.g., if test -f *.o; ...).
- - if the command 'sleep 5 && /bin/echo blah' is run interactively and
- is the sleep is stopped (^Z), the echo is run immediately in pdksh.
- In at&t ksh, the whole thing is stopped.
-
-Known differences between pdksh & at&t ksh (that are not likely to change)
- - at&t ksh seems to catch or ignore SIGALRM - pdksh dies upon receipt
- (unless it's traped of course)
- - typeset:
- - at&t ksh overloads -u/-l options: for integers, means unsigned/long,
- for strings means uppercase/lowercase; pdksh just has the
- upper/lower case (which can be useful for integers when base > 10).
- unsigned/long really should have their own options.
- - at&t ksh can't have justified integer variables
- (eg, typeset -iR5 j=10), pdksh can.
- - in pdksh, number arguments for -L/-R/-Z/-i must follow the option
- character, at&t allows it at the end of the option group (eg,
- at&t ksh likes "typeset -iu5 j", pdksh wants "typeset -i5 -u j"
- or "typeset -ui5 j"). Also, pdksh allows "typeset -i 5 j" (same
- as "typeset -i5 j"), at&t ksh does not allow this.
- - typeset -R: pdksh strips trailing space type characters (ie,
- uses isspace()), at&t ksh only skips blanks.
- - at&t ksh allows attributes of read-only variables to be changed,
- pdksh allows only the export attribute to be set.
- - (some) at&t ksh allows set -A of readonly variables, pdksh does not.
- - at&t ksh allows command assignments of readonly variables (eg, YY=2 cat),
- pdksh does not.
- - at&t ksh does not exit scripts when an implicit assignment to an integer
- variable fails due to an expression error: eg,
- echo 2+ > /tmp/x
- unset x; typeset -i x
- read x < /tmp/x
- echo still here
- prints an error and then prints "still here", similarly for
- unset x; typeset -i x
- set +A x 1 2+ 3
- echo still here
- and
- unset x y; typeset -i x y; set +A y 10 20 30
- set +A x 1 1+y[2+] 3
- echo still here
- pdksh exits a script in all the above cases. (note that both shells
- exit for:
- unset x; typeset -i x
- for x in 1 2+ 3; do echo x=$x; done
- echo still here
- ).
- - at&t ksh seems to allow function calls inside expressions
- (eg, typeset -i x='y(2)') but they do not seem to be regular functions
- nor math functions (eg, pow, exp) - anyone known anything about this?
- - `set -o nounset; unset foo; echo ${#foo}`: at&t ksh prints 0; pdksh
- generates error. Same for ${#foo[*]} and ${#foo[@]}.
- - . file: at&t ksh parses the whole file before executing anything,
- pdksh executes as it parses. This means aliases defined in the file
- will affect how pdksh parses the file, but won't affect how at&t ksh
- parses the file. Also means pdksh will not parse statements occuring
- after a (executed) return statement.
- - a return in $ENV in at&t ksh will cause the shell to exit, while in
- pdksh it will stop executing the script (this is consistent with
- what a return in .profile does in both shells).
- - at&t ksh does file globbing for `echo "${foo:-"*"}"`, pdksh does not
- (POSIX would seem to indicate pdksh is right).
- - at&t ksh thinks ${a:##foo} is ok, pdksh doesn't.
- - at&t does tilde expansion on here-document delimiters, pdksh does
- not. eg.
- $ cat << ~michael
- ~michael
- $
- works for pdksh, not for at&t ksh (POSIX seems to agree with pdksh).
- - in at&t ksh, tracked aliases have the export flag implicitly set
- and tracked aliases and normal aliases live in the same name space
- (eg, "alias" will list both tracked and normal aliases).
- in pdksh, -t does not imply -x (since -x doesn't do anything yet), and
- tracked/normal aliases live in seperate name spaces.
- in at&t ksh, alias accepts + options (eg, +x, +t) - pdksh does not.
- in pdksh, alias has a -d option to allow examination/changing of
- cached ~ entries, also unalias has -d and -t options (unalias -d
- is useful if the ~ cache gets out of date - not sure how at&t deals
- with this problem (it does cache ~ entries)).
- - at&t ksh will stop a recursive function after about 60 calls; pdksh
- will not since the limit is arbitrary and can't be controlled
- by the user (hit ^C if you get in trouble).
- - the wait command (with and without arguments) in at&t ksh will wait for
- stopped jobs when job control is enabled. pdksh doesn't.
- - at&t ksh automatically sets the bgnice option for interactive shells;
- pdksh does not.
- - in at&t ksh, "eval `false`; echo $?" prints 1, pdksh prints 0 (which
- is what POSIX says it should). Same goes for "wait `false`; echo $?".
- (same goes for "set `false`; echo $?" if posix option is set - some
- scripts that use the old getopt depend on this, so be careful about
- setting the posix option).
- - in at&t ksh, print -uX and read -uX are interrperted as -u with no
- argument (defaults to 1 and 0 respectively) and -X (which may or
- may not be a valid flag). In pdksh, -uX is interpreted as file
- descriptor X.
- - in at&t ksh, some signals (HUP, INT, QUIT) cause the read to exit, others
- (ie, everything else) do not. When it does cause exiting, anything read
- to that point is used (usually an empty line) and read returns with 0
- status. pdksh currently does similar things, but for TERM as well and
- the exit status is 128+<signal-number> - in future, pdksh's read will
- do this for all signals that are normally fatal as required by POSIX.
- (POSIX does not require the setting of variables to null so applications
- shouldn't rely on this).
- - in pdksh, ! substitution done before variable substitution; in at&t ksh
- it is done after substitution (and therefor may do ! substitutions on
- the result of variable substitutions). POSIX doesn't say which is to be
- done.
- - pwd: in at&t ksh, it ignores arguments; in pdksh, it complains when given
- arguments.
- - the at&t ksh does not do command substition on PS1, pdksh does.
- - ksh93 allows ". foo" to run the function foo if there is no file
- called foo (go figure).
- - field splitting (IFS): ksh88/ksh93 strip leading non-white space IFS
- chars, pdksh (and POSIX, I think) leave them intact. e.g.
- $ IFS="$IFS:"; read x; echo "<$x>"
- ::
- prints "<>" in at&t ksh, "<::>" in pdksh.
- - command completion: at&t ksh will do completion on a blank line (matching
- all commands), pdksh does not (as this isn't very useful - use * if
- you really want the list).
- - co-processes: if ksh93, the write portion of the co-process output is
- closed when the most recently started co-process exits. pdksh closes
- it when all the co-processes using it have exited.
-
-Oddities in ksh (pd & at&t):
- - array references inside (())/$(()) are strange:
- $(( x[2] )) does the expected, $(( $x[2] )) doesn't.
- - `typeset -R3 X='x '; echo "($X)"` produces ( x) - trailing
- spaces are stripped.
- - typeset -R turns off Z flag.
- - both shells have the following mis-feature:
- $ x='function xx {
- cat -n <<- EOF
- here we are in xx
- EOF
- }'
- $ (eval "$x"; (sleep 2; xx) & echo bye)
- [1] 1234
- bye
- $ xx: /tmp/sh1234.1: cannot open
- - bizarre special handling of alias/export/readonly/typeset arguments
- $ touch a=a; typeset a=[ab]; echo "$a"
- a=[ab]
- $ x=typeset; $x a=[ab]; echo "$a"
- a=a
- $
- - both ignore SIGTSTP,SIGTTIN,SIGTTOU in exec'd processes when talking
- and not monitoring (at&t ksh kind of does this). Doesn't really make
- sense.
- (Note that ksh.att -ic 'set +m; check-sigs' shows TSTP et al aren't
- ignored, while ksh.att -ic 'set +m^J check-sigs' does... very strange)
- - when tracing (set -x), and a command's stderr is redirected, the trace
- output is also redirected. so "set -x; echo foo 2> /tmp/O > /dev/null"
- will create /tmp/foo with the lines "+ > /dev/null" and "+ echo foo".
- - undocumented at&t ksh feature: FPATH is searched after PATH if no
- executable is found, even if typeset -uf wasn't used.
-
-at&t ksh bugs:
- [various versions:
- MIPS m120 RISC/os 5.0: Version 11/16/88d
- Dec alpha osf/1 v1.3: OSF/1 Version 11/16/88d NLS
- HP pa HP-UX 9.01: Version 11/16/88
- ]
- - (only hpux)
- $ _[2]=hi
- Bus error (core dumped)
- - (only riscos, hpux)
- $ typeset x[
- $
- - (only osf/1)
- $ A=B cat << EOF
- .$A.
- EOF
- Segmentation fault(coredump)
- $
- - (only osf/1)
- $ read "?foo "
- foo Foo
- $ set | grep Foo
- =Foo
- $
- - (all)
- $ typeset -i A
- $ typeset -L3 A
- $ typeset -l A
- Illegal instruction (core dumped)
- - (all)
- $ for i in a b c ; do echo $i, ${i[2]}, ${i[10]} ; done
- a, ,
- a, , b
- a, , c
- $
- - (all)
- $ echo ${abc:-G { I } K }
- G { I K }
- $
- $ abc=hi
- $ echo ${abc:-G { I } K }
- hi K }
- $
- The second echo should only have printed `hi'.
- - (all)
- $ echo ${abc:- > foo}
- syntax error: > unexpected
- $
- - (all? hpux) read reads too much from pipe (when pipe isn't stdin)
- print 'hi\nthere' | ksh 8<&0 0< /dev/tty
- $ read -u8 x
- $ print $x
- hi
- $ cat 0<&8
- $ read -u8 y
- $ print $y
- there
- $
- - (all)
- $ umask 0
- $ umask
- 00
- $
- - (osf, mips, !hpux)
- $ exec alias
- alias: not found
- (shell dead)
- - (all) non-white space IFS in non-substitution not preserved
- $ IFS="$IFS:"
- $ echo : "$@" # this is ok
- :
- $ echo :"$@" # this should print : too (me thinks)
-
- $
- - (only osf/1)
- $ set +m
- $ sleep 1 & # wait for a sec or two
- $ jobs
- Memory fault (core dumped)
- - (all)
- $ (sleep 1 & echo hi) &
- [1] 123
- $ [1] 234
- hi
- - (osf/1, mips)
- $ getopts abc optc -a -b -c
- $ getopts abc optc -a -b -c
- $ getopts abc optc -a
- Memory fault (core dumped)
- - (osf/1) POSIX says OPTIND shall be initialized to 1
- $ echo $OPTIND
- 0
- $
- - (osf/1 + others?)
- $ typeset -ri r=10
- $ let r=12
- $ echo $r
- 12
- $
- - (osf/1 + others?)
- $ typeset -i a
- $ typeset -L3 a
- Memory fault (core dumped)
- - (osf/1 + others?): -L strips leading \ \t\n\r, -R only strips trailing
- spaces
- $ typeset -L3 x
- $ x=' ^I^J^M 2'
- $ echo "($x)"
- (2 )
- $ typeset -R3 y
- $ x='2^I^J^M '
- $ echo "($x)"
- (^I^J^M)
- $
- - (osf/1 + others?)
- $ typeset +i RANDOM
- Memory fault (core dumped)
- - (osf/1 + others?): -L/-R/-Z clear -l/-u after assignment and vise versa
- $ typeset -u x=ab
- $ echo "($x)"
- (AB)
- $ typeset -L4 x=def
- $ echo "($x)"
- (DEF )
- $ typeset | grep ' x$'
- leftjust 4 x
- $
- $ typeset -L4 x=def
- $ echo "($x)"
- (def )
- $ typeset -u x=ab
- $ echo "($x)"
- (AB )
- $ typeset | grep ' x$'
- uppercase x
- $
- $ typeset -i x
- $ x='2()'
- $ x='()'
- $ x='2(4)'
- - (osf/1, others?)
- $ unset foo
- $ echo "${foo:-"*"}"
- <results of * expansion>
- $
- - (osf/1, others?)
- $ alias blah
- blah: alias not found
- $ alias -x blah | grep blah
- blah
- $ type blah
- Memory fault (core dumped)
- - (osf/1, others?)
- $ trap 'echo hi; false' ERR
- $ false
- hi
- hi
- ....
- Memory fault (core dumped)
- - (osf/1, others?)
- $ typeset +i ERRNO
- Memory fault (core dumped)
- - (osf/1, others?)
- $ X=abcdef
- $ echo ${X#a{b,c}e} # does not match {} inside word part of ${..#..}
- abcdefe}
- $
- - (osf/1, others?)
- $ x=f=abcdef
- $ echo ${f#a|abc}
- def
- $ echo ${f#abc|a}
- bcdef
- $ echo ${f#abc|a|d}
- abcdef
- $
- - (osf/1, hp-ux, others?)
- $ i() echo hi
- $ typeset -f
- function i
- {
- hi
- $
- - (osf/1, others?)
- $ function X {
- echo start of X
- function Y {
- echo in Y
- }
- echo end of X
- }
- $ X
- start of X
- end of X
- $ typeset -f
- function X
- {
- echo start of X
- function Y {
- echo in Y
- }
- echo end of X
- }
- function Y
- {
- echo in Y
- echo end of X
- }
- }
- $
- - (osf/1, others?)
- $ while read x; do print -r "A $x"; done |&
- [1] 18212
- $ exec 8<&p
- $ kill %1
- Memory fault
- - (osf/1, others?) Error only happens for builtin commands (/bin/echo works)
- $ while read x; do print -r "A $x"; done |&
- [1] 18212
- $ echo hi <&p
- hi
- $ echo hi <&p
- ksh: p: bad file unit number
- $ while read x; do print -r "A $x"; done |&
- ksh: process already exists
- $
- - (osf/1, others?) in restricted shells, command -p should not work.
- $ PATH=/tmp ksh -r
- $ print hi | command -p cat -n
- 1 hi
- $
- - (osf/1, others?) error message wrong for autoload files that don't define
- functions
- $ FPATH=/tmp
- $ echo echo hi there > /tmp/aja
- $ aja
- hi there
- ksh: echo: not found
- $
-
-POSIX sh questions (references are to POSIX 1003.2-1992)
- - arithmetic expressions: how are empty expressions treated?
- (eg, echo $(( ))). at&t ksh (and now pdksh) echo 0.
- Same question goes for `test "" -eq 0' - does this generate an error
- or, if not, what is the exit code?
- - should tilde expansion occur after :'s in the word part of ${..=..}?
- (me thinks it should)
- - if a signal is received during the execution of a built-in,
- does the builtin command exit or the whole shell?
- - is it legal to execute last command of pipeline in current
- execution environment (eg, can "echo foo | read bar" set
- bar?)
- - what action should be taken if there is an error doing a dup due
- to system limits (eg, not enough feil destriptors): is this
- a "redirection error" (in which case a script will exit iff the
- error occured while executing a special built-in)?
- IMHO, shell should exit script. Couldn't find a blanket statement
- like "if shell encounters an unexpected system error, it shall
- exit non-interactive scripts"...
-
-POSIX sh bugs (references are to POSIX 1003.2-1992)
- - in vi insert mode, ^W deletes to beginning of line or to the first
- blank/punct character (para at line 9124, section 3). This means
- "foo ^W" will do nothing. This is inconsistent with the vi
- spec, which says delete preceding word including and interceding
- blanks (para at line 5189, section 5).
- - parameter expansion, section 3.6.2, line 391: `in each case that a
- value of word is needed (..), word shall be subjected to tilde
- expansion, parameter expansion, ...'. Various expansions should not
- be performed if parameter is in double quotes.
- - the getopts description says assigning OPTIND a value other than 1
- produces undefined results, while the rationale for getopts suggests
- saving/restoring the OPTIND value inside functions (since POSIX
- functions don't do the save/restore automatically). Restoring
- OPTIND is kind of dumb since getopts may have been in the middle
- of parsing a group of flags (eg, -abc).
- - unclear whether arithmetic expressions (eg, $((..))) should
- understand C integer constants (ie, 0x123, 0177). at&t ksh doesn't
- and neither does pdksh.
- - `...` definition (3.6.3) says nothing about backslash followed by
- a newline, which sh and at&t ksh strip out completely. e.g.,
- $ show-args `echo 'X
- Y'`
- Number of args: 1
- 1: <XY>
- $
- POSIX would indicate the backslash-newline would be preserved.
- - does not say how "cat << ''" is to be treated (illegal, read 'til
- blank line, or read 'til eof). at&t ksh reads til eof, bourne shell
- reads 'til blank line. pdksh reads 'til blank line.
diff --git a/bin/pdksh/PROJECTS b/bin/pdksh/PROJECTS
deleted file mode 100644
index 917960ca4a0..00000000000
--- a/bin/pdksh/PROJECTS
+++ /dev/null
@@ -1,112 +0,0 @@
-$OpenBSD: PROJECTS,v 1.3 1996/10/01 02:05:30 downsj Exp $
-
-Things to be done in pdksh (see also the NOTES file):
-
- * builtin utilities:
- pdksh has most if not all POSIX/at&t ksh builtins, but they need to
- be checked that they conform to POSIX/at&t manual. Part of the
- process is changing the builtins to use the ksh_getopt() routine.
-
- The following builtins, which are defined by POSIX, haven't been
- examined:
- eval time
-
- The first pass has been done on the following commands:
- . : alias bg break cd continue echo exec exit export false fc fg
- getopts jobs kill pwd read readonly return set shift trap true umask
- unalias unset wait
-
- The second pass (ie, believed to be completely POSIX) has been done on
- the following commands:
- test
-
- (ulimit also needs to be examined to check it fits the posix style)
-
- * test suite
- Ideally, as the builtin utilities are being POSIXized, short tests
- should be written to be used in regression testing. The tests
- directory contains some tests, but many more need to be written.
-
- * internationalization
- Need to handle with the LANG and LC_* environment variables. This
- involves changes to ensure <ctype.h> macros are being used (currently
- uses its own macros in many places), figuring out how to deal with
- bases (for integer arithmetic, eg, 12#1A), and (the nasty one) doing
- string look ups for error messages, etc.. It probably isn't worth
- translating strings to other languages yet as the code is likely
- to change a lot in the near future, but it would be good to have the
- code set up so string tables can be used.
-
- * trap code
- * add the DEBUG trap.
- * fix up signal handling code. In particular, fatal vs tty signals,
- have signal routine to call to check for pending/fatal traps, etc.
-
- * parsing
- * the time keyword needs to be hacked to accept options (!) since
- POSIX says it shall accept the -p option and must skip a -- argument
- (end of options). Yuck.
-
- * lexing
- the lexing may need a re-write since it currently doesn't parse $( .. ),
- $(( .. )), (( ... )) properly.
- * need to ignore contents of quoted strings (and escaped chars?)
- inside $( .. ) and $(( .. )) when counting parentheses.
- * need to put bounds check on states[] array (if it still exists after
- the re-write)
-
- * variables
- * The "struct tbl" that is currently used for variables needs work since
- more information (eg, array stuff, fields) are needed for variables
- but not for the other things that use "struct tbl".
- * Arrays need to be implemented differently: currently does a linear
- search of a linked list to find element i; the linked list is not
- freed when a variable is unset.
-
- * functions
- finish the differences between function x and x(): trap EXIT, traps
- in general, treatment of OPTIND/OPTARG,
-
- * history
- There are two versions of the history code, COMPLEX_HISTORY and
- EASY_HISTORY, which need to be merged. COMPLEX does at&t style history
- where the history file is written after each command and checked when
- ever looking through the history (in case another shell has added
- something). EASY simply reads the history file at startup and writes
- it before exiting.
- * re-write the COMPLEX_HISTORY code so mmap() not needed (currently
- can't be used on machines without mmap()).
- * Add multiline knowledge to COMPLEX_HISTORY (see EASY_HISTORY
- stuff).
- * change COMPLEX_HISTORY code so concurrent history files are
- controlled by an option (set -o history-concurrent?). Delete
- the EASY_HISTORY code.
- * bring history code up to POSIX standards (see POSIX description
- of fc, etc.).
-
- * documentation
- Some sort of tutorial with examples would be good. Texinfo is probably
- the best medium for this. Also, the man page could be converted to
- texinfo (if the tutorial and man page are put in the same texinfo
- page, they should be somewhat distinct - i.e., the tutorial should
- be a separate thread - but there should be cross references between the
- two).
-
- * miscellaneous
- * POSIX specifies what happens when various kinds of errors occur
- in special built-ins commands vs regular commands (builtin or
- otherwise) (see POSIX.2:3.8.1). Some of this has been taken
- care of, but more needs doing.
-
- * remove static limits created by fixed sized arrays
- (eg, getsc_(line[]), ident[], heres[], PATH, states(lex.c),
- buffer size in emacs/vi code)
-
- * merge the emacs and vi code (should reduce the size of the shell and
- make maintenance easier); handle SIGWINCH while editing a line.
- [John Rochester is working on the merge]
-
- * add POSIX globbing (eg, [[:alnum:]]), see POSIX.2:2.8.3.2.
-
- * teach shf_vfprintf() about long long's (%lld); also make %p use
- long longs if appropriate.
diff --git a/bin/pdksh/README b/bin/pdksh/README
deleted file mode 100644
index f12f85b0ede..00000000000
--- a/bin/pdksh/README
+++ /dev/null
@@ -1,190 +0,0 @@
-$OpenBSD: README,v 1.5 1996/11/21 07:59:26 downsj Exp $
-
-Last updated October '96 for pdksh-5.2.12.
- (check ftp://ftp.cs.mun.ca:/pub/pdksh/ or
- http://www.cs.mun.ca/~michael/pdksh/ for new versions/patches)
-
-PD-ksh is a mostly complete AT&T ksh look-alike (see NOTES file for a list
-of things not supported). Work is currently underway to make it fully
-compatible with both POSIX and AT&T ksh (when the two don't conflict).
-
-Since pdksh is free and compiles and runs on most common unix systems, it
-is very useful in creating a consistent user interface across multiple
-machines. For example, in the CS dept. of MUN, pdksh is installed on a
-variety of machines including Suns, HPs, DecStations, pcs running Linux,
-etc., and is the login shell of ~5200 users.
-
-PDksh is currently being maintained by Michael Rendell (michael@cs.mun.ca),
-who took over from Simon J. Gerraty (sjg@zen.void.oz.au) at the later's
-suggestion. A short list of things that have been added since the last
-public pdksh release (4.9) are auto-configuration, arrays, $(( .. )),
-[[ .. ]], variable attributes, co-processes, extended file globbing,
-many POSIXisms and many bug fixes. See the NEWS and ChangeLog files for
-other features added and bugs fixed.
-
-Note that pdksh is provided AS IS, with NO WARRANTY, either expressed or
-implied. Also note that although the bulk of the code in pdksh is in the
-public domain, some files are copyrighten (but freely distributable) and
-subject to certain conditions (eg, don't remove copyright, document any
-changes, etc.). See the LEGAL file for details.
-
-If you would like to be notified via email of new releases as they become
-available, send mail to pdksh-request@cs.mun.ca with subject
-"send release notifications" (or "don't send release notifications" to stop
-them).
-
-
-Files of interest:
- NEWS short list of noticeable changes in various versions.
- CONTRIBUTORS short history of pdksh, people who contributed, etc.
- NOTES lists of known bugs in pdksh, at&t ksh, and posix.
- PROJECTS list of things that need to be done in pdksh.
- BUG-REPORTS list of recently reported bugs that have been fixed
- and all reported bugs that haven't been fixed.
- LEGAL A file detailing legal issues concerning pdksh.
- etc/* system profile and kshrc files used by Simon J. Gerraty.
- misc/README* readme files from previous versions.
- misc/Changes* changelog files from previous versions.
- os2/* files and info needed to compile ksh on os/2.
- tests/* pdksh's regression testing system.
-
-
-Compiling/Installing:
-
- The quick way:
- ./configure
- make
- make check # optional
- make install # will install /usr/local/bin/ksh
- # and /usr/local/man/man1/ksh.1
- [add path-to-installed-pdksh to /etc/shells]
-
- The more detailed description:
- * run "configure --help | your-favorite-pager" and look at the
- --enable-* and --disable-* options (they are at the end).
- Select any you options you wish to enable/disable
- (most people can skip this step).
- * run configure: this is a GNU autoconf configure script that will generate
- a Makefile and a config.h. Some of the useful options to configure are:
- --prefix=PATH indicates the directory tree under which the binary
- and man page are installed (ie, PATH/bin/ksh and
- PATH/man/man1/ksh.1).
- The default prefix is /usr/local.
- --exec-prefix=PATH overrides --prefix for machine dependent files
- (ie, the ksh binary)
- --program-prefix=pd install binary and man page as pdksh and pdksh.1
- --verbose show what is being defined as script runs
- Note that you don't have to build in the source directory. To build
- in a separate directory, do something like:
- $ mkdir objs
- $ cd objs
- $ ../configure --verbose
- ....
- $ make
- See the file INSTALL for a more complete description of configure and its
- generic options (ksh specific options are documented in the --help output)
- * miscellaneous configuration notes:
- * If your make doesn't understand VPATH, you must compile in
- the source directory.
- * On DecStations, MIPS and SONY machines with older C compilers that
- can't handle "int * volatile x", you should use gcc or turn off
- optimization. The problem is configure defines volatile to nothing
- since the compiler can't handle it properly, but the compiler does
- optimizations that the volatile is meant to prevent. So. Use gcc.
- * On MIPS RISC/os 5.0 systems, sysv environment, <signal.h> is
- messed up - it defines sigset_t, but not any of the rest of
- the posix signals (the sigset_t typedef should be in the
- ifdef KERNEL section) - also doesn't have waitpid() or wait3().
- Things compile up ok in the svr4 environment, but it dumps core
- in __start (perhaps our system doesn't have the full svr4
- environ?). Try compiling in the bsd43 environ instead (still not
- perfect - see BUG-REPORTS file), using gcc - cc has problems with
- macro expansions in the argument of a macro (in this case, the ARGS
- macro).
- * On TitanOS (Stardent/Titan), use `CC="cc -43" configure ...'.
- When configure finishes, edit config.h, undef HAVE_DIRENT_H and
- define HAVE_SYS_DIR_H (the dirent.h header file is broken).
- * On Linux (red hat distribution), check that /dev/tty has mode 0666
- (not mode 0644). If it has the wrong permissions, ksh will print
- warnings about not being able to do job control.
- * on NeXT machines (3.2, probably other releases), the siglist.out file
- won't be generated correctly if you try to use the system's compiler
- (it has a broken cc -E and strange header files). There are two
- ways to make it work:
- 1) if you have gcc, use it (for everything). Alternatively,
- force configure to use it for CPP, i.e., use
- CPP="gcc -E" configure ...
- 2) Force configure to use some extra CPPFLAGS, using
- CPPFLAGS="XXX" configure ...
- where XXX is obtained from running "cc -v YYY.c" on some
- C file. Look at the options passed to cpp (there are lots
- of them...) and replace the XXX above with them.
- Make sure you do a "make distclean" (or "rm config.cache") if
- you re-run configure with a difference CPP or CPPFLAGS.
- Also note that if you are building multiple arch binaries, you
- will have to specify both CC and CPP.
- * run make: everything should compile and link without problems.
- * run make check: this fires up a perl script that checks for some known
- and some fixed bugs. The script prints pass/fail for tests it expected
- to pass/fail, and PASS/FAIL for tests it expected to fail/pass. If you
- don't have perl, or if your perl doesn't work (most common problem is
- the .ph header files are missing or broken), you can run
- ENV= path-to-pdksh-executable misc/Bugs path-to-pdksh-executable
- instead.
- * run make install: this installs ksh (in /usr/local/bin/ksh by default,
- or where ever you told configure to put things).
- * add path-to-installed-pdksh to /etc/shells if it's not already there.
- This is only needed if you intend to use pdksh as a login shell (things
- like ftp won't allow users to connect in if their shell isn't in this
- file).
-
-The following is a list of machines that pdksh is reported to work on:
- -/PC Linux 1.x,2.x
- -/PC NetBSD 0.9a
- -/PC BSDI 1.1
- -/PC FreeBSD 2.0, 2.1
- -/PC OpenBSD
- -/PC Interactive/Sunsoft 3.0.1 and 4.1 (note that problems have been
- reported with isc3.2 - see the BUG-REPORTS file)
- -/PC OS/2
- Commadore/Amiga NetBSD 1.0
- Dec/alpha OSF/1 v2.x, v3.x
- Dec/alpha NetBSD 1.1B
- Dec/pmax Ultrix 4.2
- Dec/vax Ultrix 2.2 (not tested recently :-))
- Dec/vax 4.3BSD+NFS (MtXinu) (not tested recently :-))
- HP/pa HP-UX 9.01
- IBM/RS/6000 AIX 3.2.5
- MIPS/m120 RISC/os 5.0 (bsd43 environ)
- NeXT NeXTStep 3.2
- SGI/IRIX 6.2
- Sun/sun4 SunOS 4.1.3, 4.1.4
- Sun/sun4 Solaris 2.x
- Sun/sun386i SunOS 4.0.2
- Sun/sun3 SunOS 4.0.3, 4.1.1_U1
- Stardent/TitanOS 4.2
-
-
-Newer versions of pdksh may be available from
- ftp://ftp.cs.mun.ca:/pub/pdksh/
-you may want to check for one if you run into any problems, as the problem may
-already be fixed (you can get new release notifications automatically - see
-above).
-
-You can send bug reports, fixes, and enchancements to pdksh@cs.mun.ca (please
-don't assume I will see bug reports that are posted to some newsgroup or
-mailing list - I probably won't).
-If you are reporting a bug (with or without a fix), please include
- * the version of pdksh you are using (see version.c, or, if you are
- running pdksh, try echo $KSH_VERSION),
- * the machine, operating system and compiler you are using,
- * and a description of how to repeat the bug (a small shell
- script that demonstrates the bug is best).
-as well as the following, if relevant (if you aren't sure, include them)
- * what options you are using (both configure options and set -o options)
- * the output of configure, with the verbose flag
- (eg, make distclean; ./configure --verbose)
- * the contents of config.log (this is created by the configure script)
- * if you are using gcc (the GNU C compiler), which version it is.
-
-Michael Rendell, michael@cs.mun.ca.
diff --git a/bin/pdksh/alloc.c b/bin/pdksh/alloc.c
deleted file mode 100644
index bc39b1bc045..00000000000
--- a/bin/pdksh/alloc.c
+++ /dev/null
@@ -1,288 +0,0 @@
-/* $OpenBSD: alloc.c,v 1.1 1996/08/14 06:19:10 downsj Exp $ */
-
-/*
- * area-based allocation built on malloc/free
- */
-
-#include "sh.h"
-#ifdef MEM_DEBUG
-# undef alloc
-# undef aresize
-# undef afree
-#endif /* MEM_DEBUG */
-
-#define ICELLS 100 /* number of Cells in small Block */
-
-typedef union Cell Cell;
-typedef struct Block Block;
-
-/*
- * The Cells in a Block are organized as a set of objects.
- * Each object (pointed to by dp) begins with a size in (dp-1)->size,
- * followed with "size" data Cells. Free objects are
- * linked together via dp->next.
- */
-
-union Cell {
- size_t size;
- Cell *next;
- struct {int _;} junk; /* alignment */
-};
-
-struct Block {
- Block *next; /* list of Blocks in Area */
- Cell *freelist; /* object free list */
- Cell *last; /* &b.cell[size] */
- Cell cell [1]; /* [size] Cells for allocation */
-};
-
-static Block aempty = {&aempty, aempty.cell, aempty.cell};
-
-/* create empty Area */
-Area *
-ainit(ap)
- register Area *ap;
-{
- ap->freelist = &aempty;
- return ap;
-}
-
-/* free all object in Area */
-void
-afreeall(ap)
- register Area *ap;
-{
- register Block *bp;
- register Block *tmp;
-
- bp = ap->freelist;
- if (bp != NULL && bp != &aempty) {
- do {
- tmp = bp->next;
- free((void*)bp);
- bp = tmp;
- } while (bp != ap->freelist);
- ap->freelist = &aempty;
- }
-}
-
-/* allocate object from Area */
-void *
-alloc(size, ap)
- size_t size;
- register Area *ap;
-{
- int cells, split;
- register Block *bp;
- register Cell *dp, *fp, *fpp;
-
- if (size <= 0) {
- aerror(ap, "allocate bad size");
- return NULL;
- }
- cells = (unsigned)(size - 1) / sizeof(Cell) + 1;
-
- /* find Cell large enough */
- for (bp = ap->freelist; ; bp = bp->next) {
- for (fpp = NULL, fp = bp->freelist;
- fp != bp->last; fpp = fp, fp = fpp->next)
- if ((fp-1)->size >= cells)
- goto Found;
-
- /* wrapped around Block list, create new Block */
- if (bp->next == ap->freelist) {
- bp = (Block*) malloc(offsetof(Block, cell[ICELLS])
- + sizeof(bp->cell[0]) * cells);
- if (bp == NULL) {
- aerror(ap, "cannot allocate");
- return NULL;
- }
- if (ap->freelist == &aempty)
- bp->next = bp;
- else {
- bp->next = ap->freelist->next;
- ap->freelist->next = bp;
- }
- bp->last = bp->cell + ICELLS + cells;
- fp = bp->freelist = bp->cell + 1; /* initial free list */
- (fp-1)->size = ICELLS + cells - 1;
- fp->next = bp->last;
- fpp = NULL;
- break;
- }
- }
- Found:
- ap->freelist = bp;
- dp = fp; /* allocated object */
- split = (dp-1)->size - cells;
- if (split < 0)
- aerror(ap, "allocated object too small");
- if (--split <= 0) { /* allocate all */
- fp = fp->next;
- } else { /* allocate head, free tail */
- (fp-1)->size = cells;
- fp += cells + 1;
- (fp-1)->size = split;
- fp->next = dp->next;
- }
- if (fpp == NULL)
- bp->freelist = fp;
- else
- fpp->next = fp;
- return (void*) dp;
-}
-
-/* change size of object -- like realloc */
-void *
-aresize(ptr, size, ap)
- register void *ptr;
- size_t size;
- Area *ap;
-{
- int cells;
- register Cell *dp = (Cell*) ptr;
-
- if (size <= 0) {
- aerror(ap, "allocate bad size");
- return NULL;
- }
- cells = (unsigned)(size - 1) / sizeof(Cell) + 1;
-
- if (dp == NULL || (dp-1)->size < cells) { /* enlarge object */
- /* XXX check for available adjacent free block */
- ptr = alloc(size, ap);
- if (dp != NULL) {
- memcpy(ptr, dp, (dp-1)->size * sizeof(Cell));
- afree((void *) dp, ap);
- }
- } else { /* shrink object */
- int split;
-
- split = (dp-1)->size - cells;
- if (--split <= 0) /* cannot split */
- ;
- else { /* shrink head, free tail */
- (dp-1)->size = cells;
- dp += cells + 1;
- (dp-1)->size = split;
- afree((void*)dp, ap);
- }
- }
- return (void*) ptr;
-}
-
-void
-afree(ptr, ap)
- void *ptr;
- register Area *ap;
-{
- register Block *bp;
- register Cell *fp, *fpp;
- register Cell *dp = (Cell*)ptr;
-
- /* find Block containing Cell */
- for (bp = ap->freelist; ; bp = bp->next) {
- if (bp->cell <= dp && dp < bp->last)
- break;
- if (bp->next == ap->freelist) {
- aerror(ap, "freeing with invalid area");
- return;
- }
- }
-
- /* find position in free list */
- for (fpp = NULL, fp = bp->freelist; fp < dp; fpp = fp, fp = fpp->next)
- ;
-
- if (fp == dp) {
- aerror(ap, "freeing free object");
- return;
- }
-
- /* join object with next */
- if (dp + (dp-1)->size == fp-1) { /* adjacent */
- (dp-1)->size += (fp-1)->size + 1;
- dp->next = fp->next;
- } else /* non-adjacent */
- dp->next = fp;
-
- /* join previous with object */
- if (fpp == NULL)
- bp->freelist = dp;
- else if (fpp + (fpp-1)->size == dp-1) { /* adjacent */
- (fpp-1)->size += (dp-1)->size + 1;
- fpp->next = dp->next;
- } else /* non-adjacent */
- fpp->next = dp;
-}
-
-#if DEBUG_ALLOC
-void
-aprint(ap, ptr, size)
- register Area *ap;
- void *ptr;
- size_t size;
-{
- Block *bp;
-
- if (!ap)
- shellf("aprint: null area pointer\n");
- else if (!(bp = ap->freelist))
- shellf("aprint: null area freelist\n");
- else if (bp == &aempty)
- shellf("aprint: area is empty\n");
- else {
- int i;
- Cell *fp;
-
- for (i = 0; !i || bp != ap->freelist; bp = bp->next, i++) {
- if (ptr) {
- void *eptr = (void *) (((char *) ptr) + size);
- /* print block only if it overlaps ptr/size */
- if (!((ptr >= (void *) bp
- && ptr <= (void *) bp->last)
- || (eptr >= (void *) bp
- && eptr <= (void *) bp->last)))
- continue;
- shellf("aprint: overlap of 0x%p .. 0x%p\n",
- ptr, eptr);
- }
- shellf("aprint: block %2d: 0x%p .. 0x%p (%d)\n", i,
- bp->cell, bp->last,
- (char *) bp->last - (char *) bp->cell);
- for (fp = bp->freelist; fp != bp->last; fp = fp->next)
- shellf(
- "aprint: 0x%p .. 0x%p (%d) free\n",
- (fp-1), (fp-1) + (fp-1)->size,
- (fp-1)->size * sizeof(Cell));
- }
- }
-}
-#endif /* DEBUG_ALLOC */
-
-
-#ifdef TEST_ALLOC
-
-Area a;
-
-main(int argc, char **argv) {
- int i;
- char *p [9];
-
- ainit(&a);
- for (i = 0; i < 9; i++) {
- p[i] = alloc(124, &a);
- printf("alloc: %x\n", p[i]);
- }
- for (i = 1; i < argc; i++)
- afree(p[atoi(argv[i])], &a);
- afreeall(&a);
- return 0;
-}
-
-void aerror(Area *ap, const char *msg) {
- abort();
-}
-
-#endif
-
diff --git a/bin/pdksh/c_ksh.c b/bin/pdksh/c_ksh.c
deleted file mode 100644
index 1435aa9c57d..00000000000
--- a/bin/pdksh/c_ksh.c
+++ /dev/null
@@ -1,1402 +0,0 @@
-/* $OpenBSD: c_ksh.c,v 1.7 1997/06/19 13:58:37 kstailey Exp $ */
-
-/*
- * built-in Korn commands: c_*
- */
-
-#include "sh.h"
-#include "ksh_stat.h"
-#include <ctype.h>
-
-int
-c_cd(wp)
- char **wp;
-{
- int optc;
- int physical = Flag(FPHYSICAL);
- int cdnode; /* was a node from cdpath added in? */
- int printpath = 0; /* print where we cd'd? */
- int rval;
- struct tbl *pwd_s, *oldpwd_s;
- XString xs;
- char *xp;
- char *dir, *try, *pwd;
- int phys_path;
- char *cdpath;
-
- while ((optc = ksh_getopt(wp, &builtin_opt, "LP")) != EOF)
- switch (optc) {
- case 'L':
- physical = 0;
- break;
- case 'P':
- physical = 1;
- break;
- case '?':
- return 1;
- }
- wp += builtin_opt.optind;
-
- if (Flag(FRESTRICTED)) {
- bi_errorf("restricted shell - can't cd");
- return 1;
- }
-
- pwd_s = global("PWD");
- oldpwd_s = global("OLDPWD");
-
- if (!wp[0]) {
- /* No arguments - go home */
- if ((dir = str_val(global("HOME"))) == null) {
- bi_errorf("no home directory (HOME not set)");
- return 1;
- }
- } else if (!wp[1]) {
- /* One argument: - or dir */
- dir = wp[0];
- if (strcmp(dir, "-") == 0) {
- dir = str_val(oldpwd_s);
- if (dir == null) {
- bi_errorf("no OLDPWD");
- return 1;
- }
- printpath++;
- }
- } else if (!wp[2]) {
- /* Two arguments - substitute arg1 in PWD for arg2 */
- int ilen, olen, nlen, elen;
- char *cp;
-
- if (!current_wd[0]) {
- bi_errorf("don't know current directory");
- return 1;
- }
- /* substitue arg1 for arg2 in current path.
- * if the first substitution fails because the cd fails
- * we could try to find another substitution. For now
- * we don't
- */
- if ((cp = strstr(current_wd, wp[0])) == (char *) 0) {
- bi_errorf("bad substitution");
- return 1;
- }
- ilen = cp - current_wd;
- olen = strlen(wp[0]);
- nlen = strlen(wp[1]);
- elen = strlen(current_wd + ilen + olen) + 1;
- dir = alloc(ilen + nlen + elen, ATEMP);
- memcpy(dir, current_wd, ilen);
- memcpy(dir + ilen, wp[1], nlen);
- memcpy(dir + ilen + nlen, current_wd + ilen + olen, elen);
- printpath++;
- } else {
- bi_errorf("too many arguments");
- return 1;
- }
-
- Xinit(xs, xp, PATH, ATEMP);
- /* xp will have a bogus value after make_path() - set it to 0
- * so that if it's used, it will cause a dump
- */
- xp = (char *) 0;
-
- cdpath = str_val(global("CDPATH"));
- do {
- cdnode = make_path(current_wd, dir, &cdpath, &xs, &phys_path);
-#ifdef S_ISLNK
- if (physical)
- rval = chdir(try = Xstring(xs, xp) + phys_path);
- else
-#endif /* S_ISLNK */
- {
- simplify_path(Xstring(xs, xp));
- rval = chdir(try = Xstring(xs, xp));
- }
- } while (rval < 0 && cdpath != (char *) 0);
-
- if (rval < 0) {
- if (cdnode)
- bi_errorf("%s: bad directory", dir);
- else
- bi_errorf("%s - %s", try, strerror(errno));
- return 1;
- }
-
- /* Clear out tracked aliases with relative paths */
- flushcom(0);
-
- /* Set OLDPWD */
- if (current_wd[0])
- setstr(oldpwd_s, current_wd);
-
- if (!ISABSPATH(Xstring(xs, xp))) {
-#ifdef OS2
- /* simplify_path() doesn't know about os/2's drive contexts,
- * so it can't set current_wd when changing to a:foo.
- * Handle this by calling getcwd()...
- */
- pwd = ksh_get_wd((char *) 0, 0);
-#else /* OS2 */
- pwd = (char *) 0;
-#endif /* OS2 */
- } else
-#ifdef S_ISLNK
- if (!physical || !(pwd = get_phys_path(Xstring(xs, xp))))
-#endif /* S_ISLNK */
- pwd = Xstring(xs, xp);
-
- /* Set PWD */
- if (pwd) {
- set_current_wd(pwd);
- setstr(pwd_s, pwd);
- } else {
- set_current_wd(null);
- pwd = Xstring(xs, xp);
- /* XXX unset $PWD? */
- }
- if (printpath || cdnode)
- shprintf("%s\n", pwd);
-
- return 0;
-}
-
-int
-c_pwd(wp)
- char **wp;
-{
- int optc;
- int physical = Flag(FPHYSICAL);
- char *p;
-
- while ((optc = ksh_getopt(wp, &builtin_opt, "LP")) != EOF)
- switch (optc) {
- case 'L':
- physical = 0;
- break;
- case 'P':
- physical = 1;
- break;
- case '?':
- return 1;
- }
- wp += builtin_opt.optind;
-
- if (wp[0]) {
- bi_errorf("too many arguments");
- return 1;
- }
-#ifdef S_ISLNK
- p = current_wd[0] ? (physical ? get_phys_path(current_wd) : current_wd)
- : (char *) 0;
-#else /* S_ISLNK */
- p = current_wd[0] ? current_wd : (char *) 0;
-#endif /* S_ISLNK */
- if (p && eaccess(p, R_OK) < 0)
- p = (char *) 0;
- if (!p) {
- p = ksh_get_wd((char *) 0, 0);
- if (!p) {
- bi_errorf("can't get current directory - %s",
- strerror(errno));
- return 1;
- }
- }
- shprintf("%s\n", p);
- return 0;
-}
-
-int
-c_print(wp)
- char **wp;
-{
-#define PO_NL BIT(0) /* print newline */
-#define PO_EXPAND BIT(1) /* expand backslash sequences */
-#define PO_PMINUSMINUS BIT(2) /* print a -- argument */
-#define PO_HIST BIT(3) /* print to history instead of stdout */
-#define PO_COPROC BIT(4) /* printing to coprocess: block SIGPIPE */
-#define PO_FSLASH BIT(5) /* swap slash for backslash (for os2 ) */
- int fd = 1;
- int flags = PO_EXPAND|PO_NL;
- char *s;
- const char *emsg;
- XString xs;
- char *xp;
-
- if (wp[0][0] == 'e') { /* echo command */
- int nflags = flags;
-
- /* A compromise between sysV and BSD echo commands:
- * escape sequences are enabled by default, and
- * -n, -e and -E are recognized if they appear
- * in arguments with no illegal options (ie, echo -nq
- * will print -nq).
- * Different from sysV echo since options are recognized,
- * different from BSD echo since escape sequences are enabled
- * by default.
- */
- wp += 1;
- while ((s = *wp) && *s == '-' && s[1]) {
- while (*++s)
- if (*s == 'n')
- nflags &= ~PO_NL;
- else if (*s == 'e')
- nflags |= PO_EXPAND;
- else if (*s == 'E')
- nflags &= ~PO_EXPAND;
- else
- /* bad option: don't use nflags, print
- * argument
- */
- break;
- if (*s)
- break;
- wp++;
- flags = nflags;
- }
- } else {
- int optc;
-#if OS2
- const char *options = "Rnpfrsu,"; /* added f flag */
-#else
- const char *options = "Rnprsu,";
-#endif
- while ((optc = ksh_getopt(wp, &builtin_opt, options)) != EOF)
- switch (optc) {
- case 'R': /* fake BSD echo command */
- flags |= PO_PMINUSMINUS;
- flags &= ~PO_EXPAND;
- options = "ne";
- break;
- case 'e':
- flags |= PO_EXPAND;
- break;
-#ifdef OS2
- case 'f':
- flags |= PO_FSLASH;
- break;
-#endif
- case 'n':
- flags &= ~PO_NL;
- break;
-#ifdef KSH
- case 'p':
- if ((fd = coproc_getfd(W_OK, &emsg)) < 0) {
- bi_errorf("-p: %s", emsg);
- return 1;
- }
- break;
-#endif /* KSH */
- case 'r':
- flags &= ~PO_EXPAND;
- break;
- case 's':
- flags |= PO_HIST;
- break;
- case 'u':
- if (!*(s = builtin_opt.optarg))
- fd = 0;
- else if ((fd = check_fd(s, W_OK, &emsg)) < 0) {
- bi_errorf("-u: %s: %s", s, emsg);
- return 1;
- }
- break;
- case '?':
- return 1;
- }
- if (!(builtin_opt.info & GI_MINUSMINUS)) {
- /* treat a lone - like -- */
- if (wp[builtin_opt.optind]
- && strcmp(wp[builtin_opt.optind], "-") == 0)
- builtin_opt.optind++;
- } else if (flags & PO_PMINUSMINUS)
- builtin_opt.optind--;
- wp += builtin_opt.optind;
- }
-
- Xinit(xs, xp, 128, ATEMP);
-
- while (*wp != NULL) {
- register int c;
- s = *wp;
- while ((c = *s++) != '\0') {
- Xcheck(xs, xp);
-#ifdef OS2
- if ((flags & PO_FSLASH) && c == '\\')
- if (*s == '\\')
- *s++;
- else
- c = '/';
-#endif /* OS2 */
- if ((flags & PO_EXPAND) && c == '\\') {
- int i;
-
- switch ((c = *s++)) {
- /* Oddly enough, \007 seems more portable than
- * \a (due to HP-UX cc, Ultrix cc, old pcc's,
- * etc.).
- */
- case 'a': c = '\007'; break;
- case 'b': c = '\b'; break;
- case 'c': flags &= ~PO_NL;
- continue; /* AT&T brain damage */
- case 'f': c = '\f'; break;
- case 'n': c = '\n'; break;
- case 'r': c = '\r'; break;
- case 't': c = '\t'; break;
- case 'v': c = 0x0B; break;
- case '0':
- /* Look for an octal number: can have
- * three digits (not counting the
- * leading 0). Truely burnt.
- */
- c = 0;
- for (i = 0; i < 3; i++) {
- if (*s >= '0' && *s <= '7')
- c = c*8 + *s++ - '0';
- else
- break;
- }
- break;
- case '\0': s--; c = '\\'; break;
- case '\\': break;
- default:
- Xput(xs, xp, '\\');
- }
- }
- Xput(xs, xp, c);
- }
- if (*++wp != NULL)
- Xput(xs, xp, ' ');
- }
- if (flags & PO_NL)
- Xput(xs, xp, '\n');
-
- if (flags & PO_HIST) {
- Xput(xs, xp, '\0');
- source->line++;
- histsave(source->line, Xstring(xs, xp), 1);
- Xfree(xs, xp);
- } else {
- int n, len = Xlength(xs, xp);
- int UNINITIALIZED(opipe);
-#ifdef KSH
-
- /* Ensure we aren't killed by a SIGPIPE while writing to
- * a coprocess. at&t ksh doesn't seem to do this (seems
- * to just check that the co-process is alive, which is
- * not enough).
- */
- if (coproc.write >= 0 && coproc.write == fd) {
- flags |= PO_COPROC;
- opipe = block_pipe();
- }
-#endif /* KSH */
- for (s = Xstring(xs, xp); len > 0; ) {
- n = write(fd, s, len);
- if (n < 0) {
-#ifdef KSH
- if (flags & PO_COPROC)
- restore_pipe(opipe);
-#endif /* KSH */
- if (errno == EINTR) {
- /* allow user to ^C out */
- intrcheck();
-#ifdef KSH
- if (flags & PO_COPROC)
- opipe = block_pipe();
-#endif /* KSH */
- continue;
- }
-#ifdef KSH
- /* This doesn't really make sense - could
- * break scripts (print -p generates
- * error message).
- *if (errno == EPIPE)
- * coproc_write_close(fd);
- */
-#endif /* KSH */
- return 1;
- }
- s += n;
- len -= n;
- }
-#ifdef KSH
- if (flags & PO_COPROC)
- restore_pipe(opipe);
-#endif /* KSH */
- }
-
- return 0;
-}
-
-int
-c_whence(wp)
- char **wp;
-{
- struct tbl *tp;
- char *id;
- int pflag = 0, vflag = 0, Vflag = 0;
- int ret = 0;
- int optc;
- int iam_whence = wp[0][0] == 'w';
- int fcflags;
- const char *options = iam_whence ? "pv" : "pvV";
-
- while ((optc = ksh_getopt(wp, &builtin_opt, options)) != EOF)
- switch (optc) {
- case 'p':
- pflag = 1;
- break;
- case 'v':
- vflag = 1;
- break;
- case 'V':
- Vflag = 1;
- break;
- case '?':
- return 1;
- }
- wp += builtin_opt.optind;
-
-
- fcflags = FC_BI | FC_PATH | FC_FUNC;
- if (!iam_whence) {
- /* Note that -p on its own is deal with in comexec() */
- if (pflag)
- fcflags |= FC_DEFPATH;
- /* Convert command options to whence options - note that
- * command -pV uses a different path search than whence -v
- * or whence -pv. This should be considered a feature.
- */
- vflag = Vflag;
- }
- if (pflag)
- fcflags &= ~(FC_BI | FC_FUNC);
-
- while ((vflag || ret == 0) && (id = *wp++) != NULL) {
- tp = NULL;
- if ((iam_whence || vflag) && !pflag)
- tp = tsearch(&keywords, id, hash(id));
- if (!tp && !pflag) {
- tp = tsearch(&aliases, id, hash(id));
- if (tp && !(tp->flag & ISSET))
- tp = NULL;
- }
- if (!tp)
- tp = findcom(id, fcflags);
- if (vflag || (tp->type != CALIAS && tp->type != CEXEC
- && tp->type != CTALIAS))
- shprintf("%s", id);
- switch (tp->type) {
- case CKEYWD:
- if (vflag)
- shprintf(" is a reserved word");
- break;
- case CALIAS:
- if (vflag)
- shprintf(" is an %salias for ",
- (tp->flag & EXPORT) ? "exported "
- : null);
- if (!iam_whence && !vflag)
- shprintf("alias %s=", id);
- print_value_quoted(tp->val.s);
- break;
- case CFUNC:
- if (vflag) {
- shprintf(" is a");
- if (tp->flag & EXPORT)
- shprintf("n exported");
- if (tp->flag & TRACE)
- shprintf(" traced");
- if (!(tp->flag & ISSET)) {
- shprintf(" undefined");
- if (tp->u.fpath)
- shprintf(" (autoload from %s)",
- tp->u.fpath);
- }
- shprintf(" function");
- }
- break;
- case CSHELL:
- if (vflag)
- shprintf(" is a%s shell builtin",
- (tp->flag & SPEC_BI) ? " special" : null);
- break;
- case CTALIAS:
- case CEXEC:
- if (tp->flag & ISSET) {
- if (vflag) {
- shprintf(" is ");
- if (tp->type == CTALIAS)
- shprintf(
- "a tracked %salias for ",
- (tp->flag & EXPORT) ?
- "exported "
- : null);
- }
- shprintf("%s", tp->val.s);
- } else {
- if (vflag)
- shprintf(" not found");
- ret = 1;
- }
- break;
- default:
- shprintf("%s is *GOK*", id);
- break;
- }
- if (vflag || !ret)
- shprintf(newline);
- }
- return ret;
-}
-
-/* Deal with command -vV - command -p dealt with in comexec() */
-int
-c_command(wp)
- char **wp;
-{
- /* Let c_whence do the work. Note that c_command() must be
- * a distinct function from c_whence() (tested in comexec()).
- */
- return c_whence(wp);
-}
-
-/* typeset, export, and readonly */
-int
-c_typeset(wp)
- char **wp;
-{
- struct block *l = e->loc;
- struct tbl *vp, **p;
- Tflag fset = 0, fclr = 0;
- int thing = 0, func = 0, local = 0;
- const char *options = "L#R#UZ#fi#lrtux"; /* see comment below */
- char *fieldstr, *basestr;
- int field, base;
- int optc;
- Tflag flag;
- int pflag = 0;
-
- switch (**wp) {
- case 'e': /* export */
- fset |= EXPORT;
- options = "p";
- break;
- case 'r': /* readonly */
- fset |= RDONLY;
- options = "p";
- break;
- case 's': /* set */
- /* called with 'typeset -' */
- break;
- case 't': /* typeset */
- local = 1;
- break;
- }
-
- fieldstr = basestr = (char *) 0;
- builtin_opt.flags |= GF_PLUSOPT;
- /* at&t ksh seems to have 0-9 as options, which are multiplied
- * to get a number that is used with -L, -R, -Z or -i (eg, -1R2
- * sets right justify in a field of 12). This allows options
- * to be grouped in an order (eg, -Lu12), but disallows -i8 -L3 and
- * does not allow the number to be specified as a seperate argument
- * Here, the number must follow the RLZi option, but is optional
- * (see the # kludge in ksh_getopt()).
- */
- while ((optc = ksh_getopt(wp, &builtin_opt, options)) != EOF) {
- flag = 0;
- switch (optc) {
- case 'L':
- flag |= LJUST;
- fieldstr = builtin_opt.optarg;
- break;
- case 'R':
- flag |= RJUST;
- fieldstr = builtin_opt.optarg;
- break;
- case 'U':
- /* at&t ksh uses u, but this conflicts with
- * upper/lower case. If this option is changed,
- * need to change the -U below as well
- */
- flag |= INT_U;
- break;
- case 'Z':
- flag |= ZEROFIL;
- fieldstr = builtin_opt.optarg;
- break;
- case 'f':
- func = 1;
- break;
- case 'i':
- flag |= INTEGER;
- basestr = builtin_opt.optarg;
- break;
- case 'l':
- flag |= LCASEV;
- break;
- case 'p': /* posix export/readonly -p flag */
- pflag = 1;
- break;
- case 'r':
- flag |= RDONLY;
- break;
- case 't':
- flag |= TRACE;
- break;
- case 'u':
- flag |= UCASEV_AL; /* upper case / autoload */
- break;
- case 'x':
- flag |= EXPORT;
- break;
- case '?':
- return 1;
- }
- if (builtin_opt.info & GI_PLUS) {
- fclr |= flag;
- fset &= ~flag;
- thing = '+';
- } else {
- fset |= flag;
- fclr &= ~flag;
- thing = '-';
- }
- }
-
- field = 0;
- if (fieldstr && !bi_getn(fieldstr, &field))
- return 1;
- base = 0;
- if (basestr && !bi_getn(basestr, &base))
- return 1;
-
- if (!(builtin_opt.info & GI_MINUSMINUS) && wp[builtin_opt.optind]
- && (wp[builtin_opt.optind][0] == '-'
- || wp[builtin_opt.optind][0] == '+')
- && wp[builtin_opt.optind][1] == '\0')
- {
- thing = wp[builtin_opt.optind][0];
- builtin_opt.optind++;
- }
-
- if (func && ((fset|fclr) & ~(TRACE|UCASEV_AL|EXPORT))) {
- bi_errorf("only -t, -u and -x options may be used with -f");
- return 1;
- }
- if (wp[builtin_opt.optind]) {
- /* Take care of exclusions */
- /* setting these attributes clears the others, unless they
- * are also set in this command
- */
- if (fset & (LJUST|RJUST|ZEROFIL|UCASEV_AL|LCASEV|INTEGER
- |INT_U|INT_L))
- fclr |= ~fset &
- (LJUST|RJUST|ZEROFIL|UCASEV_AL|LCASEV|INTEGER
- |INT_U|INT_L);
- fclr &= ~fset; /* set wins */
- if ((fset & (ZEROFIL|LJUST)) == ZEROFIL) {
- fset |= RJUST;
- fclr &= ~RJUST;
- }
- if (fset & LCASEV) /* LCASEV has priority */
- fclr |= UCASEV_AL;
- else if (fset & UCASEV_AL)
- fclr |= LCASEV;
- if (fset & LJUST) /* LJUST has priority */
- fclr |= RJUST;
- else if (fset & RJUST)
- fclr |= LJUST;
- if ((fset | fclr) & INTEGER) {
- if (!(fset | fclr) & INT_U)
- fclr |= INT_U;
- if (!(fset | fclr) & INT_L)
- fclr |= INT_L;
- }
- fset &= ~fclr; /* in case of something like -LR */
- }
-
- /* set variables and attributes */
- if (wp[builtin_opt.optind]) {
- int i;
- int rval = 0;
- struct tbl *f;
-
- if (local && !func)
- fset |= LOCAL;
- for (i = builtin_opt.optind; wp[i]; i++) {
- if (func) {
- f = findfunc(wp[i], hash(wp[i]),
- (fset&UCASEV_AL) ? TRUE : FALSE);
- if (!f) {
- /* at&t ksh does ++rval: bogus */
- rval = 1;
- continue;
- }
- if (fset | fclr) {
- f->flag |= fset;
- f->flag &= ~fclr;
- } else
- fptreef(shl_stdout, 0,
- "function %s %T\n",
- wp[i], f->val.t);
- } else if (!typeset(wp[i], fset, fclr, field, base)) {
- bi_errorf("%s: not identifier", wp[i]);
- return 1;
- }
- }
- return rval;
- }
-
- /* list variables and attributes */
- flag = fset | fclr; /* no difference at this point.. */
- if (func) {
- for (l = e->loc; l; l = l->next) {
- for (p = tsort(&l->funs); (vp = *p++); ) {
- if (flag && (vp->flag & flag) == 0)
- continue;
- if (thing == '-')
- fptreef(shl_stdout, 0, "function %s %T\n",
- vp->name, vp->val.t);
- else
- shprintf("%s\n", vp->name);
- }
- }
- } else {
- for (l = e->loc; l; l = l->next) {
- for (p = tsort(&l->vars); (vp = *p++); )
- for (; vp; vp = vp->u.array) {
- /* Report an unset param only if the user has
- * explicitly given it some attribute (like export);
- * otherwise, after "echo $FOO", we would report FOO...
- */
- if (!(vp->flag & ISSET) && !(vp->flag & USERATTRIB))
- continue;
- if (flag && (vp->flag & flag) == 0)
- continue;
- /* no arguments */
- if (thing == 0 && flag == 0) {
- /* at&t ksh prints things like export, integer,
- * leftadj, zerofill, etc., but POSIX says must
- * be suitable for re-entry...
- */
- shprintf("typeset ");
- if ((vp->flag&INTEGER))
- shprintf("-i ");
- if ((vp->flag&EXPORT))
- shprintf("-x ");
- if ((vp->flag&RDONLY))
- shprintf("-r ");
- if ((vp->flag&TRACE))
- shprintf("-t ");
- if ((vp->flag&LJUST))
- shprintf("-L%d ", vp->u2.field);
- if ((vp->flag&RJUST))
- shprintf("-R%d ", vp->u2.field);
- if ((vp->flag&ZEROFIL))
- shprintf("-Z ");
- if ((vp->flag&LCASEV))
- shprintf("-l ");
- if ((vp->flag&UCASEV_AL))
- shprintf("-u ");
- if ((vp->flag&INT_U))
- shprintf("-U ");
- if (vp->flag&ARRAY)
- shprintf("%s[%d]\n", vp->name,vp->index);
- else
- shprintf("%s\n", vp->name);
- } else {
- if (pflag)
- shprintf("%s ",
- (flag & EXPORT) ? "export" : "readonly");
- if (vp->flag&ARRAY)
- shprintf("%s[%d]", vp->name, vp->index);
- else
- shprintf("%s", vp->name);
- if (thing == '-' && (vp->flag&ISSET)) {
- char *s = str_val(vp);
-
- shprintf("=");
- /* at&t ksh can't have justified integers.. */
- if ((vp->flag & (INTEGER|LJUST|RJUST))
- == INTEGER)
- shprintf("%s", s);
- else
- print_value_quoted(s);
- }
- shprintf(newline);
- }
- }
- }
- }
- return 0;
-}
-
-int
-c_alias(wp)
- char **wp;
-{
- struct table *t = &aliases;
- int rv = 0, rflag = 0, tflag, Uflag = 0;
- Tflag xflag = 0;
- int optc;
-
- while ((optc = ksh_getopt(wp, &builtin_opt, "drtUx")) != EOF)
- switch (optc) {
- case 'd':
- t = &homedirs;
- break;
- case 'r':
- rflag = 1;
- break;
- case 't':
- t = &taliases;
- break;
- case 'U': /* kludge for tracked alias initialization
- * (don't do a path search, just make an entry)
- */
- Uflag = 1;
- break;
- case 'x':
- xflag = EXPORT;
- break;
- case '?':
- return 1;
- }
- wp += builtin_opt.optind;
-
- tflag = t == &taliases;
-
- /* "hash -r" means reset all the tracked aliases.. */
- if (rflag) {
- static const char *const args[] = {
- "unalias", "-ta", (const char *) 0
- };
-
- if (!tflag || *wp) {
- shprintf(
- "alias: -r flag can only be used with -t and without arguments\n");
- return 1;
- }
- ksh_getopt_reset(&builtin_opt, GF_ERROR);
- return c_unalias((char **) args);
- }
-
- if (*wp == NULL) {
- struct tbl *ap, **p;
-
- for (p = tsort(t); (ap = *p++) != NULL; )
- if ((ap->flag & (ISSET|xflag)) == (ISSET|xflag)) {
- shprintf("%s=", ap->name);
- print_value_quoted(ap->val.s);
- shprintf(newline);
- }
- }
-
- for (; *wp != NULL; wp++) {
- char *alias = *wp;
- char *val = strchr(alias, '=');
- char *newval;
- struct tbl *ap;
- int h;
-
- if (val)
- alias = str_nsave(alias, val++ - alias, ATEMP);
- h = hash(alias);
- if (val == NULL && !tflag && !xflag) {
- ap = tsearch(t, alias, h);
- if (ap != NULL && (ap->flag&ISSET)) {
- shprintf("%s=", ap->name);
- print_value_quoted(ap->val.s);
- shprintf(newline);
- } else {
- shprintf("%s alias not found\n", alias);
- rv = 1;
- }
- continue;
- }
- ap = tenter(t, alias, h);
- ap->type = tflag ? CTALIAS : CALIAS;
- /* Are we setting the value or just some flags? */
- if ((val && !tflag) || (!val && tflag && !Uflag)) {
- if (ap->flag&ALLOC) {
- ap->flag &= ~(ALLOC|ISSET);
- afree((void*)ap->val.s, APERM);
- }
- /* ignore values for -t (at&t ksh does this) */
- newval = tflag ? search(alias, path, X_OK, (int *) 0)
- : val;
- if (newval) {
- ap->val.s = str_save(newval, APERM);
- ap->flag |= ALLOC|ISSET;
- } else
- ap->flag &= ~ISSET;
- }
- ap->flag |= DEFINED|xflag;
- if (val)
- afree(alias, ATEMP);
- }
-
- return rv;
-}
-
-int
-c_unalias(wp)
- char **wp;
-{
- register struct table *t = &aliases;
- register struct tbl *ap;
- int rv = 0, all = 0;
- int optc;
-
- while ((optc = ksh_getopt(wp, &builtin_opt, "adt")) != EOF)
- switch (optc) {
- case 'a':
- all = 1;
- break;
- case 'd':
- t = &homedirs;
- break;
- case 't':
- t = &taliases;
- break;
- case '?':
- return 1;
- }
- wp += builtin_opt.optind;
-
- for (; *wp != NULL; wp++) {
- ap = tsearch(t, *wp, hash(*wp));
- if (ap == NULL) {
- rv = 1; /* POSIX */
- continue;
- }
- if (ap->flag&ALLOC) {
- ap->flag &= ~(ALLOC|ISSET);
- afree((void*)ap->val.s, APERM);
- }
- ap->flag &= ~(DEFINED|ISSET|EXPORT);
- }
-
- if (all) {
- struct tstate ts;
-
- for (twalk(&ts, t); (ap = tnext(&ts)); ) {
- if (ap->flag&ALLOC) {
- ap->flag &= ~(ALLOC|ISSET);
- afree((void*)ap->val.s, APERM);
- }
- ap->flag &= ~(DEFINED|ISSET|EXPORT);
- }
- }
-
- return rv;
-}
-
-#ifdef KSH
-int
-c_let(wp)
- char **wp;
-{
- int rv = 1;
- long val;
-
- if (wp[1] == (char *) 0) /* at&t ksh does this */
- bi_errorf("no arguments");
- else
- for (wp++; *wp; wp++)
- if (!evaluate(*wp, &val, TRUE)) {
- rv = 2; /* distinguish error from zero result */
- break;
- } else
- rv = val == 0;
- return rv;
-}
-#endif /* KSH */
-
-int
-c_jobs(wp)
- char **wp;
-{
- int optc;
- int flag = 0;
- int nflag = 0;
- int rv = 0;
-
- while ((optc = ksh_getopt(wp, &builtin_opt, "lpnz")) != EOF)
- switch (optc) {
- case 'l':
- flag = 1;
- break;
- case 'p':
- flag = 2;
- break;
- case 'n':
- nflag = 1;
- break;
- case 'z': /* debugging: print zombies */
- nflag = -1;
- break;
- case '?':
- return 1;
- }
- wp += builtin_opt.optind;
- if (!*wp)
- if (j_jobs((char *) 0, flag, nflag))
- rv = 1;
- else
- for (; *wp; wp++)
- if (j_jobs(*wp, flag, nflag))
- rv = 1;
- return rv;
-}
-
-#ifdef JOBS
-int
-c_fgbg(wp)
- char **wp;
-{
- int bg = strcmp(*wp, "bg") == 0;
- int UNINITIALIZED(rv);
-
- if (!Flag(FMONITOR)) {
- bi_errorf("job control not enabled");
- return 1;
- }
- if (ksh_getopt(wp, &builtin_opt, null) == '?')
- return 1;
- wp += builtin_opt.optind;
- if (*wp)
- for (; *wp; wp++)
- rv = j_resume(*wp, bg);
- else
- rv = j_resume("%%", bg);
- /* POSIX says fg shall return 0 (unless an error occurs).
- * at&t ksh returns the exit value of the job...
- */
- return (bg || Flag(FPOSIX)) ? 0 : rv;
-}
-#endif
-
-struct kill_info {
- int num_width;
- int name_width;
-};
-static char *kill_fmt_entry ARGS((void *arg, int i, char *buf, int buflen));
-
-/* format a single kill item */
-static char *
-kill_fmt_entry(arg, i, buf, buflen)
- void *arg;
- int i;
- char *buf;
- int buflen;
-{
- struct kill_info *ki = (struct kill_info *) arg;
-
- i++;
- if (sigtraps[i].name)
- shf_snprintf(buf, buflen, "%*d %*s %s",
- ki->num_width, i,
- ki->name_width, sigtraps[i].name,
- sigtraps[i].mess);
- else
- shf_snprintf(buf, buflen, "%*d %*d %s",
- ki->num_width, i,
- ki->name_width, sigtraps[i].signal,
- sigtraps[i].mess);
- return buf;
-}
-
-
-int
-c_kill(wp)
- char **wp;
-{
- Trap *t = (Trap *) 0;
- char *p;
- int lflag = 0;
- int i, n, rv, sig;
-
- /* assume old style options if -digits or -UPPERCASE */
- if ((p = wp[1]) && *p == '-' && (digit(p[1]) || isupper(p[1]))) {
- if (!(t = gettrap(p + 1))) {
- bi_errorf("bad signal `%s'", p + 1);
- return 1;
- }
- i = (wp[2] && strcmp(wp[2], "--") == 0) ? 3 : 2;
- } else {
- int optc;
-
- while ((optc = ksh_getopt(wp, &builtin_opt, "ls:")) != EOF)
- switch (optc) {
- case 'l':
- lflag = 1;
- break;
- case 's':
- if (!(t = gettrap(builtin_opt.optarg))) {
- bi_errorf("bad signal `%s'",
- builtin_opt.optarg);
- return 1;
- }
- case '?':
- return 1;
- }
- i = builtin_opt.optind;
- }
- if ((lflag && t) || (!wp[i] && !lflag)) {
- shf_fprintf(shl_out,
-"Usage: kill [ -s signame | -signum | -signame ] {pid|job}...\n\
- kill -l [exit_status]\n"
- );
- bi_errorf(null);
- return 1;
- }
-
- if (lflag) {
- if (wp[i]) {
- for (; wp[i]; i++) {
- if (!bi_getn(wp[i], &n))
- return 1;
- if (n > 128 && n < 128 + SIGNALS)
- n -= 128;
- if (n > 0 && n < SIGNALS && sigtraps[n].name)
- shprintf("%s\n", sigtraps[n].name);
- else
- shprintf("%d\n", n);
- }
- } else if (Flag(FPOSIX)) {
- p = null;
- for (i = 1; i < SIGNALS; i++, p = space)
- if (sigtraps[i].name)
- shprintf("%s%s", p, sigtraps[i].name);
- shprintf(newline);
- } else {
- int w, i;
- int mess_width;
- struct kill_info ki;
-
- for (i = SIGNALS, ki.num_width = 1; i >= 10; i /= 10)
- ki.num_width++;
- ki.name_width = mess_width = 0;
- for (i = 0; i < SIGNALS; i++) {
- w = sigtraps[i].name ? strlen(sigtraps[i].name)
- : ki.num_width;
- if (w > ki.name_width)
- ki.name_width = w;
- w = strlen(sigtraps[i].mess);
- if (w > mess_width)
- mess_width = w;
- }
-
- print_columns(shl_stdout, SIGNALS - 1,
- kill_fmt_entry, (void *) &ki,
- ki.num_width + ki.name_width + mess_width + 3);
- }
- return 0;
- }
- rv = 0;
- sig = t ? t->signal : SIGTERM;
- for (; (p = wp[i]); i++) {
- if (*p == '%') {
- if (j_kill(p, sig))
- rv = 1;
- } else if (!getn(p, &n)) {
- bi_errorf("%s: arguments must be jobs or process ids",
- p);
- rv = 1;
- } else {
- /* use killpg if < -1 since -1 does special things for
- * some non-killpg-endowed kills
- */
- if ((n < -1 ? killpg(-n, sig) : kill(n, sig)) < 0) {
- bi_errorf("%s: %s", p, strerror(errno));
- rv = 1;
- }
- }
- }
- return rv;
-}
-
-static Getopt user_opt; /* parsing state for getopts builtin command */
-static int getopts_noset; /* stop OPTIND assign from resetting state */
-
-void
-getopts_reset(val)
- int val;
-{
- if (!getopts_noset && val >= 1) {
- ksh_getopt_reset(&user_opt,
- GF_NONAME | (Flag(FPOSIX) ? 0 : GF_PLUSOPT));
- user_opt.optind = val;
- }
-}
-
-int
-c_getopts(wp)
- char **wp;
-{
- int argc;
- const char *options;
- const char *var;
- int optc;
- char buf[3];
- struct tbl *vq;
-
- if (ksh_getopt(wp, &builtin_opt, null) == '?')
- return 1;
- wp += builtin_opt.optind;
-
- options = *wp++;
- if (!options) {
- bi_errorf("missing options argument");
- return 1;
- }
-
- var = *wp++;
- if (!var) {
- bi_errorf("missing name argument");
- return 1;
- }
- if (!*var || *skip_varname(var, TRUE)) {
- bi_errorf("%s: is not an identifier", var);
- return 1;
- }
-
- if (e->loc->next == (struct block *) 0) {
- internal_errorf(0, "c_getopts: no argv");
- return 1;
- }
- /* Which arguments are we parsing... */
- if (*wp == (char *) 0)
- wp = e->loc->next->argv;
- else
- *--wp = e->loc->next->argv[0];
-
- /* Check that our saved state won't cause a core dump... */
- for (argc = 0; wp[argc]; argc++)
- ;
- if (user_opt.optind > argc
- || (user_opt.p != 0
- && user_opt.p > strlen(wp[user_opt.optind - 1])))
- {
- bi_errorf("arguments changed since last call");
- return 1;
- }
-
- user_opt.optarg = (char *) 0;
- optc = ksh_getopt(wp, &user_opt, options);
-
- if (optc >= 0 && optc != '?' && (user_opt.info & GI_PLUS)) {
- buf[0] = '+';
- buf[1] = optc;
- buf[2] = '\0';
- } else {
- /* POSIX says var is set to ? at end-of-options, at&t ksh
- * sets it to null - we go with POSIX...
- */
- buf[0] = optc < 0 ? '?' : optc;
- buf[1] = '\0';
- }
-
- /* at&t ksh does not change OPTIND if it was an unknown option.
- * Scripts counting on this are prone to break... (ie, don't count
- * on this staying).
- */
- if (optc != '?') {
- getopts_noset = 1;
- setint(global("OPTIND"), (long) user_opt.optind);
- getopts_noset = 0;
- }
-
- if (user_opt.optarg == (char *) 0)
- unset(global("OPTARG"), 0);
- else
- setstr(global("OPTARG"), user_opt.optarg);
-
- vq = global(var);
- if (vq->flag & RDONLY) {
- bi_errorf("%s is readonly", var);
- return 1;
- }
- if (Flag(FEXPORT))
- typeset(var, EXPORT, 0, 0, 0);
- setstr(vq, buf);
-
- return optc < 0 ? 1 : 0;
-}
-
-#ifdef EMACS
-int
-c_bind(wp)
- char **wp;
-{
- int rv = 0, macro = 0, list = 0;
- register char *cp;
- int optc;
-
- while ((optc = ksh_getopt(wp, &builtin_opt, "lm")) != EOF)
- switch (optc) {
- case 'l':
- list = 1;
- break;
- case 'm':
- macro = 1;
- break;
- case '?':
- return 1;
- }
- wp += builtin_opt.optind;
-
- if (*wp == NULL) /* list all */
- rv = x_bind((char*)NULL, (char*)NULL, 0, list);
-
- for (; *wp != NULL; wp++) {
- cp = strchr(*wp, '=');
- if (cp != NULL)
- *cp++ = '\0';
- if (x_bind(*wp, cp, macro, 0))
- rv = 1;
- }
-
- return rv;
-}
-#endif
-
-/* A leading = means assignments before command are kept;
- * a leading * means a POSIX special builtin;
- * a leading + means a POSIX regular builtin
- * (* and + should not be combined).
- */
-const struct builtin kshbuiltins [] = {
- {"+alias", c_alias}, /* no =: at&t manual wrong */
- {"+cd", c_cd},
- {"+command", c_command},
- {"echo", c_print},
- {"*=export", c_typeset},
-#ifdef HISTORY
- {"+fc", c_fc},
-#endif /* HISTORY */
- {"+getopts", c_getopts},
- {"+jobs", c_jobs},
- {"+kill", c_kill},
-#ifdef KSH
- {"let", c_let},
-#endif /* KSH */
- {"print", c_print},
- {"pwd", c_pwd},
- {"*=readonly", c_typeset},
- {"=typeset", c_typeset},
- {"+unalias", c_unalias},
- {"whence", c_whence},
-#ifdef JOBS
- {"+bg", c_fgbg},
- {"+fg", c_fgbg},
-#endif
-#ifdef EMACS
- {"bind", c_bind},
-#endif
- {NULL, NULL}
-};
diff --git a/bin/pdksh/c_sh.c b/bin/pdksh/c_sh.c
deleted file mode 100644
index 0691aa51af5..00000000000
--- a/bin/pdksh/c_sh.c
+++ /dev/null
@@ -1,787 +0,0 @@
-/* $OpenBSD: c_sh.c,v 1.6 1997/08/05 21:49:54 grr Exp $ */
-
-/*
- * built-in Bourne commands
- */
-
-#include "sh.h"
-#include "ksh_stat.h" /* umask() */
-#include "ksh_time.h"
-#include "ksh_times.h"
-
-static char *clocktos ARGS((clock_t t));
-
-/* :, false and true */
-int
-c_label(wp)
- char **wp;
-{
- return wp[0][0] == 'f' ? 1 : 0;
-}
-
-int
-c_shift(wp)
- char **wp;
-{
- register struct block *l = e->loc;
- register int n;
- long val;
- char *arg;
-
- if (ksh_getopt(wp, &builtin_opt, null) == '?')
- return 1;
- arg = wp[builtin_opt.optind];
-
- if (arg) {
- evaluate(arg, &val, FALSE);
- n = val;
- } else
- n = 1;
- if (n < 0) {
- bi_errorf("%s: bad number", arg);
- return (1);
- }
- if (l->argc < n) {
- bi_errorf("nothing to shift");
- return (1);
- }
- l->argv[n] = l->argv[0];
- l->argv += n;
- l->argc -= n;
- return 0;
-}
-
-int
-c_umask(wp)
- char **wp;
-{
- register int i;
- register char *cp;
- int symbolic = 0;
- int old_umask;
- int optc;
-
- while ((optc = ksh_getopt(wp, &builtin_opt, "S")) != EOF)
- switch (optc) {
- case 'S':
- symbolic = 1;
- break;
- case '?':
- return 1;
- }
- cp = wp[builtin_opt.optind];
- if (cp == NULL) {
- old_umask = umask(0);
- umask(old_umask);
- if (symbolic) {
- char buf[18];
- int j;
-
- old_umask = ~old_umask;
- cp = buf;
- for (i = 0; i < 3; i++) {
- *cp++ = "ugo"[i];
- *cp++ = '=';
- for (j = 0; j < 3; j++)
- if (old_umask & (1 << (8 - (3*i + j))))
- *cp++ = "rwx"[j];
- *cp++ = ',';
- }
- cp[-1] = '\0';
- shprintf("%s\n", buf);
- } else
- shprintf("%#3.3o\n", old_umask);
- } else {
- int new_umask;
-
- if (digit(*cp)) {
- for (new_umask = 0; *cp >= '0' && *cp <= '7'; cp++)
- new_umask = new_umask * 8 + (*cp - '0');
- if (*cp) {
- bi_errorf("bad number");
- return 1;
- }
- } else {
- /* symbolic format */
- int positions, new_val;
- char op;
-
- old_umask = umask(0);
- umask(old_umask); /* in case of error */
- old_umask = ~old_umask;
- new_umask = old_umask;
- positions = 0;
- while (*cp) {
- while (*cp && strchr("augo", *cp))
- switch (*cp++) {
- case 'a': positions |= 0111; break;
- case 'u': positions |= 0100; break;
- case 'g': positions |= 0010; break;
- case 'o': positions |= 0001; break;
- }
- if (!positions)
- positions = 0111; /* default is a */
- if (!strchr("=+-", op = *cp))
- break;
- cp++;
- new_val = 0;
- while (*cp && strchr("rwxugoXs", *cp))
- switch (*cp++) {
- case 'r': new_val |= 04; break;
- case 'w': new_val |= 02; break;
- case 'x': new_val |= 01; break;
- case 'u': new_val |= old_umask >> 6;
- break;
- case 'g': new_val |= old_umask >> 3;
- break;
- case 'o': new_val |= old_umask >> 0;
- break;
- case 'X': if (old_umask & 0111)
- new_val |= 01;
- break;
- case 's': /* ignored */
- break;
- }
- new_val = (new_val & 07) * positions;
- switch (op) {
- case '-':
- new_umask &= ~new_val;
- break;
- case '=':
- new_umask = new_val
- | (new_umask & ~(positions * 07));
- break;
- case '+':
- new_umask |= new_val;
- }
- if (*cp == ',') {
- positions = 0;
- cp++;
- } else if (!strchr("=+-", *cp))
- break;
- }
- if (*cp) {
- bi_errorf("bad mask");
- return 1;
- }
- new_umask = ~new_umask;
- }
- umask(new_umask);
- }
- return 0;
-}
-
-int
-c_dot(wp)
- char **wp;
-{
- char *file, *cp;
- char **argv;
- int argc;
- int i;
-
- if (ksh_getopt(wp, &builtin_opt, null) == '?')
- return 1;
-
- if ((cp = wp[builtin_opt.optind]) == NULL)
- return 0;
- file = search(cp, path, R_OK, (int *) 0);
- if (file == NULL) {
- bi_errorf("%s: not found", cp);
- return 1;
- }
-
- /* Set positional parameters? */
- if (wp[builtin_opt.optind + 1]) {
- argv = wp + builtin_opt.optind;
- argv[0] = e->loc->argv[0]; /* preserve $0 */
- for (argc = 0; argv[argc + 1]; argc++)
- ;
- } else {
- argc = 0;
- argv = (char **) 0;
- }
- i = include(file, argc, argv, 0);
- if (i < 0) { /* should not happen */
- bi_errorf("%s: %s", cp, strerror(errno));
- return 1;
- }
- return i;
-}
-
-int
-c_wait(wp)
- char **wp;
-{
- int UNINITIALIZED(rv);
- int sig;
-
- if (ksh_getopt(wp, &builtin_opt, null) == '?')
- return 1;
- wp += builtin_opt.optind;
- if (*wp == (char *) 0) {
- while (waitfor((char *) 0, &sig) >= 0)
- ;
- rv = sig;
- } else {
- for (; *wp; wp++)
- rv = waitfor(*wp, &sig);
- if (rv < 0)
- rv = sig ? sig : 127; /* magic exit code: bad job-id */
- }
- return rv;
-}
-
-int
-c_read(wp)
- char **wp;
-{
- register int c = 0;
- int expand = 1, history = 0;
- int expanding;
- int ecode = 0;
- register char *cp;
- int fd = 0;
- struct shf *shf;
- int optc;
- const char *emsg;
- XString cs, xs;
- struct tbl *vp;
- char UNINITIALIZED(*xp);
-
- while ((optc = ksh_getopt(wp, &builtin_opt, "prsu,")) != EOF)
- switch (optc) {
-#ifdef KSH
- case 'p':
- if ((fd = coproc_getfd(R_OK, &emsg)) < 0) {
- bi_errorf("-p: %s", emsg);
- return 1;
- }
- break;
-#endif /* KSH */
- case 'r':
- expand = 0;
- break;
- case 's':
- history = 1;
- break;
- case 'u':
- if (!*(cp = builtin_opt.optarg))
- fd = 0;
- else if ((fd = check_fd(cp, R_OK, &emsg)) < 0) {
- bi_errorf("-u: %s: %s", cp, emsg);
- return 1;
- }
- break;
- case '?':
- return 1;
- }
- wp += builtin_opt.optind;
-
- if (*wp == NULL)
- *--wp = "REPLY";
-
- /* Since we can't necessarily seek backwards on non-regular files,
- * don't buffer them so we can't read too much.
- */
- shf = shf_reopen(fd, SHF_RD | SHF_INTERRUPT | can_seek(fd), shl_spare);
-
- if ((cp = strchr(*wp, '?')) != NULL) {
- *cp = 0;
- if (isatty(fd)) {
- /* at&t ksh says it prints prompt on fd if it's open
- * for writing and is a tty, but it doesn't do it
- * (it also doesn't check the interactive flag,
- * as is indicated in the Kornshell book).
- */
- shellf("%s", cp+1);
- }
- }
-
-#ifdef KSH
- /* If we are reading from the co-process for the first time,
- * make sure the other side of the pipe is closed first. This allows
- * the detection of eof.
- *
- * This is not compatiable with at&t ksh... the fd is kept so another
- * coproc can be started with same ouput, however, this means eof
- * can't be detected... This is why it is closed here.
- * If this call is removed, remove the eof check below, too.
- * coproc_readw_close(fd);
- */
-#endif /* KSH */
-
- if (history)
- Xinit(xs, xp, 128, ATEMP);
- expanding = 0;
- Xinit(cs, cp, 128, ATEMP);
- for (; *wp != NULL; wp++) {
- for (cp = Xstring(cs, cp); ; ) {
- if (c == '\n' || c == EOF)
- break;
- while (1) {
- c = shf_getc(shf);
- if (c == '\0'
-#ifdef OS2
- || c == '\r'
-#endif /* OS2 */
- )
- continue;
- if (c == EOF && shf_error(shf)
- && shf_errno(shf) == EINTR)
- {
- /* Was the offending signal one that
- * would normally kill a process?
- * If so, pretend the read was killed.
- */
- ecode = fatal_trap_check();
-
- /* non fatal (eg, CHLD), carry on */
- if (!ecode) {
- shf_clearerr(shf);
- continue;
- }
- }
- break;
- }
- if (history) {
- Xcheck(xs, xp);
- Xput(xs, xp, c);
- }
- Xcheck(cs, cp);
- if (expanding) {
- expanding = 0;
- if (c == '\n') {
- c = 0;
- if (Flag(FTALKING) && isatty(fd)) {
- /* set prompt in case this is
- * called from .profile or $ENV
- */
- set_prompt(PS2, (Source *) 0);
- pprompt(prompt, 0);
- }
- } else if (c != EOF)
- Xput(cs, cp, c);
- continue;
- }
- if (expand && c == '\\') {
- expanding = 1;
- continue;
- }
- if (c == '\n' || c == EOF)
- break;
- if (ctype(c, C_IFS)) {
- if (Xlength(cs, cp) == 0 && ctype(c, C_IFSWS))
- continue;
- if (wp[1])
- break;
- }
- Xput(cs, cp, c);
- }
- /* strip trailing IFS white space from last variable */
- if (!wp[1])
- while (Xlength(cs, cp) && ctype(cp[-1], C_IFS)
- && ctype(cp[-1], C_IFSWS))
- cp--;
- Xput(cs, cp, '\0');
- vp = global(*wp);
- if (vp->flag & RDONLY) {
- shf_flush(shf);
- bi_errorf("%s is read only", *wp);
- return 1;
- }
- if (Flag(FEXPORT))
- typeset(*wp, EXPORT, 0, 0, 0);
- setstr(vp, Xstring(cs, cp));
- }
-
- shf_flush(shf);
- if (history) {
- Xput(xs, xp, '\0');
- source->line++;
- histsave(source->line, Xstring(xs, xp), 1);
- Xfree(xs, xp);
- }
-#ifdef KSH
- /* if this is the co-process fd, close the file descriptor
- * (can get eof if and only if all processes are have died, ie,
- * coproc.njobs is 0 and the pipe is closed).
- */
- if (c == EOF && !ecode)
- coproc_read_close(fd);
-#endif /* KSH */
-
- return ecode ? ecode : c == EOF;
-}
-
-int
-c_eval(wp)
- char **wp;
-{
- register struct source *s;
-
- if (ksh_getopt(wp, &builtin_opt, null) == '?')
- return 1;
- s = pushs(SWORDS, ATEMP);
- s->u.strv = wp + builtin_opt.optind;
- return shell(s, FALSE);
-}
-
-int
-c_trap(wp)
- char **wp;
-{
- int i;
- char *s;
- register Trap *p;
-
- if (ksh_getopt(wp, &builtin_opt, null) == '?')
- return 1;
- wp += builtin_opt.optind;
-
- if (*wp == NULL) {
- int anydfl = 0;
-
- for (p = sigtraps, i = SIGNALS+1; --i >= 0; p++) {
- if (p->trap == NULL)
- anydfl = 1;
- else {
- shprintf("trap -- ");
- print_value_quoted(p->trap);
- shprintf(" %s\n", p->name);
- }
- }
-#if 0 /* this is ugly and not clear POSIX needs it */
- /* POSIX may need this so output of trap can be saved and
- * used to restore trap conditions
- */
- if (anydfl) {
- shprintf("trap -- -");
- for (p = sigtraps, i = SIGNALS+1; --i >= 0; p++)
- if (p->trap == NULL && p->name)
- shprintf(" %s", p->name);
- shprintf(newline);
- }
-#endif
- return 0;
- }
-
- s = (gettrap(*wp) == NULL) ? *wp++ : NULL; /* get command */
- if (s != NULL && s[0] == '-' && s[1] == '\0')
- s = NULL;
-
- /* set/clear traps */
- while (*wp != NULL) {
- p = gettrap(*wp++);
- if (p == NULL) {
- bi_errorf("bad signal %s", wp[-1]);
- return 1;
- }
- settrap(p, s);
- }
- return 0;
-}
-
-int
-c_exitreturn(wp)
- char **wp;
-{
- int how = LEXIT;
- char *arg;
-
- if (ksh_getopt(wp, &builtin_opt, null) == '?')
- return 1;
- arg = wp[builtin_opt.optind];
-
- if (arg != NULL && !getn(arg, &exstat)) {
- exstat = 1;
- warningf(TRUE, "%s: bad number", arg);
- }
- if (wp[0][0] == 'r') { /* return */
- struct env *ep;
-
- /* need to tell if this is exit or return so trap exit will
- * work right (POSIX)
- */
- for (ep = e; ep; ep = ep->oenv)
- if (STOP_RETURN(ep->type)) {
- how = LRETURN;
- break;
- }
- }
-
- if (how == LEXIT && !really_exit && j_stopped_running()) {
- really_exit = 1;
- how = LSHELL;
- }
-
- quitenv(); /* get rid of any i/o redirections */
- unwind(how);
- /*NOTREACHED*/
- return 0;
-}
-
-int
-c_brkcont(wp)
- char **wp;
-{
- int n, quit;
- struct env *ep, *last_ep = (struct env *) 0;
- char *arg;
-
- if (ksh_getopt(wp, &builtin_opt, null) == '?')
- return 1;
- arg = wp[builtin_opt.optind];
-
- if (!arg)
- n = 1;
- else if (!bi_getn(arg, &n))
- return 1;
- quit = n;
- if (quit <= 0) {
- /* at&t ksh does this for non-interactive shells only - weird */
- bi_errorf("%s: bad value", arg);
- return 1;
- }
-
- /* Stop at E_NONE, E_PARSE, E_FUNC, or E_INCL */
- for (ep = e; ep && !STOP_BRKCONT(ep->type); ep = ep->oenv)
- if (ep->type == E_LOOP) {
- if (--quit == 0)
- break;
- ep->flags |= EF_BRKCONT_PASS;
- last_ep = ep;
- }
-
- if (quit) {
- /* at&t ksh doesn't print a message - just does what it
- * can. We print a message 'cause it helps in debugging
- * scripts, but don't generate an error (ie, keep going).
- */
- if (n == quit) {
- warningf(TRUE, "%s: cannot %s", wp[0], wp[0]);
- return 0;
- }
- /* POSIX says if n is too big, the last enclosing loop
- * shall be used. Doesn't say to print an error but we
- * do anyway 'cause the user messed up.
- */
- last_ep->flags &= ~EF_BRKCONT_PASS;
- warningf(TRUE, "%s: can only %s %d level(s)",
- wp[0], wp[0], n - quit);
- }
-
- unwind(*wp[0] == 'b' ? LBREAK : LCONTIN);
- /*NOTREACHED*/
-}
-
-int
-c_set(wp)
- char **wp;
-{
- int argi, setargs;
- struct block *l = e->loc;
- register char **owp = wp;
-
- if (wp[1] == NULL) {
- static const char *const args [] = { "set", "-", NULL };
- return c_typeset((char **) args);
- }
-
- argi = parse_args(wp, OF_SET, &setargs);
- if (argi < 0)
- return 1;
- /* set $# and $* */
- if (setargs) {
- owp = wp += argi - 1;
- wp[0] = l->argv[0]; /* save $0 */
- while (*++wp != NULL)
- *wp = str_save(*wp, &l->area);
- l->argc = wp - owp - 1;
- l->argv = (char **) alloc(sizeofN(char *, l->argc+2), &l->area);
- for (wp = l->argv; (*wp++ = *owp++) != NULL; )
- ;
- }
- /* POSIX says set exit status is 0, but old scripts that use
- * getopt(1), use the construct: set -- `getopt ab:c "$@"`
- * which assumes the exit value set will be that of the ``
- * (subst_exstat is cleared in execute() so that it will be 0
- * if there are no command substitutions).
- */
- return Flag(FPOSIX) ? 0 : subst_exstat;
-}
-
-int
-c_unset(wp)
- char **wp;
-{
- register char *id;
- int optc, unset_var = 1;
- int ret = 0;
-
- while ((optc = ksh_getopt(wp, &builtin_opt, "fv")) != EOF)
- switch (optc) {
- case 'f':
- unset_var = 0;
- break;
- case 'v':
- unset_var = 1;
- break;
- case '?':
- return 1;
- }
- wp += builtin_opt.optind;
- for (; (id = *wp) != NULL; wp++)
- if (unset_var) { /* unset variable */
- struct tbl *vp = global(id);
-
- if (!(vp->flag & ISSET))
- ret = 1;
- if ((vp->flag&RDONLY)) {
- bi_errorf("%s is read only", vp->name);
- return 1;
- }
- unset(vp, strchr(id, '[') ? 1 : 0);
- } else { /* unset function */
- if (define(id, (struct op *) NULL))
- ret = 1;
- }
- return ret;
-}
-
-int
-c_times(wp)
- char **wp;
-{
- struct tms all;
-
- (void) ksh_times(&all);
- shprintf("Shell: %8s user ", clocktos(all.tms_utime));
- shprintf("%8s system\n", clocktos(all.tms_stime));
- shprintf("Kids: %8s user ", clocktos(all.tms_cutime));
- shprintf("%8s system\n", clocktos(all.tms_cstime));
-
- return 0;
-}
-
-/*
- * time pipeline (really a statement, not a built-in command)
- */
-int
-timex(t, f)
- struct op *t;
- int f;
-{
- int rv;
- struct tms t0, t1;
- clock_t t0t, t1t;
- extern clock_t j_usrtime, j_systime; /* computed by j_wait */
-
- j_usrtime = j_systime = 0;
- t0t = ksh_times(&t0);
- rv = execute(t->left, f);
- t1t = ksh_times(&t1);
-
- shf_fprintf(shl_out, "%8s real ", clocktos(t1t - t0t));
- shf_fprintf(shl_out, "%8s user ",
- clocktos(t1.tms_utime - t0.tms_utime + j_usrtime));
- shf_fprintf(shl_out, "%8s system ",
- clocktos(t1.tms_stime - t0.tms_stime + j_systime));
- shf_fprintf(shl_out, newline);
-
- return rv;
-}
-
-static char *
-clocktos(t)
- clock_t t;
-{
- static char temp[20];
- register int i;
- register char *cp = temp + sizeof(temp);
-
- if (CLK_TCK != 100) /* convert to 1/100'ths */
- t = (t < 1000000000/CLK_TCK) ?
- (t * 100) / CLK_TCK : (t / CLK_TCK) * 100;
-
- *--cp = '\0';
- *--cp = 's';
- for (i = -2; i <= 0 || t > 0; i++) {
- if (i == 0)
- *--cp = '.';
- *--cp = '0' + (char)(t%10);
- t /= 10;
- }
- return cp;
-}
-
-/* exec with no args - args case is taken care of in comexec() */
-int
-c_exec(wp)
- char ** wp;
-{
- int i;
-
- /* make sure redirects stay in place */
- if (e->savefd != NULL) {
- for (i = 0; i < NUFILE; i++) {
- if (e->savefd[i] > 0)
- close(e->savefd[i]);
- /* keep anything > 2 private */
- if (!Flag(FSH) && i > 2 && e->savefd[i])
- fd_clexec(i);
- }
- e->savefd = NULL;
- }
- return 0;
-}
-
-/* dummy function, special case in comexec() */
-int
-c_builtin(wp)
- char ** wp;
-{
- return 0;
-}
-
-extern int c_test ARGS((char **wp)); /* in c_test.c */
-extern int c_ulimit ARGS((char **wp)); /* in c_ulimit.c */
-
-/* A leading = means assignments before command are kept;
- * a leading * means a POSIX special builtin;
- * a leading + means a POSIX regular builtin
- * (* and + should not be combined).
- */
-const struct builtin shbuiltins [] = {
- {"*=.", c_dot},
- {"*=:", c_label},
- {"[", c_test},
- {"*=break", c_brkcont},
- {"=builtin", c_builtin},
- {"*=continue", c_brkcont},
- {"*=eval", c_eval},
- {"*=exec", c_exec},
- {"*=exit", c_exitreturn},
- {"+false", c_label},
- {"*=return", c_exitreturn},
- {"*=set", c_set},
- {"*=shift", c_shift},
- {"=times", c_times},
- {"*=trap", c_trap},
- {"+=wait", c_wait},
- {"+read", c_read},
- {"test", c_test},
- {"+true", c_label},
- {"ulimit", c_ulimit},
- {"+umask", c_umask},
- {"*=unset", c_unset},
-#ifdef OS2
- /* In OS2, the first line of a file can be "extproc name", which
- * tells the command interpreter (cmd.exe) to use name to execute
- * the file. For this to be useful, ksh must ignore commands
- * starting with extproc and this does the trick...
- */
- {"extproc", c_label},
-#endif /* OS2 */
- {NULL, NULL}
-};
diff --git a/bin/pdksh/c_test.c b/bin/pdksh/c_test.c
deleted file mode 100644
index 16703ff4960..00000000000
--- a/bin/pdksh/c_test.c
+++ /dev/null
@@ -1,616 +0,0 @@
-/* $OpenBSD: c_test.c,v 1.4 1997/06/19 13:58:38 kstailey Exp $ */
-
-/*
- * test(1); version 7-like -- author Erik Baalbergen
- * modified by Eric Gisin to be used as built-in.
- * modified by Arnold Robbins to add SVR3 compatibility
- * (-x -c -b -p -u -g -k) plus Korn's -L -nt -ot -ef and new -S (socket).
- * modified by Michael Rendell to add Korn's [[ .. ]] expressions.
- * modified by J.T. Conklin to add POSIX compatibility.
- */
-
-#include "sh.h"
-#include "ksh_stat.h"
-#include "c_test.h"
-
-/* test(1) accepts the following grammar:
- oexpr ::= aexpr | aexpr "-o" oexpr ;
- aexpr ::= nexpr | nexpr "-a" aexpr ;
- nexpr ::= primary | "!" nexpr ;
- primary ::= unary-operator operand
- | operand binary-operator operand
- | operand
- | "(" oexpr ")"
- ;
-
- unary-operator ::= "-a"|"-r"|"-w"|"-x"|"-e"|"-f"|"-d"|"-c"|"-b"|"-p"|
- "-u"|"-g"|"-k"|"-s"|"-t"|"-z"|"-n"|"-o"|"-O"|"-G"|
- "-L"|"-h"|"-S"|"-H";
-
- binary-operator ::= "="|"=="|"!="|"-eq"|"-ne"|"-ge"|"-gt"|"-le"|"-lt"|
- "-nt"|"-ot"|"-ef"|
- "<"|">" # rules used for [[ .. ]] expressions
- ;
- operand ::= <any thing>
-*/
-
-#define T_ERR_EXIT 2 /* POSIX says > 1 for errors */
-
-struct t_op {
- char op_text[4];
- Test_op op_num;
-};
-static const struct t_op u_ops [] = {
- {"-a", TO_FILAXST },
- {"-b", TO_FILBDEV },
- {"-c", TO_FILCDEV },
- {"-d", TO_FILID },
- {"-e", TO_FILEXST },
- {"-f", TO_FILREG },
- {"-G", TO_FILGID },
- {"-g", TO_FILSETG },
- {"-h", TO_FILSYM },
- {"-H", TO_FILCDF },
- {"-k", TO_FILSTCK },
- {"-L", TO_FILSYM },
- {"-n", TO_STNZE },
- {"-O", TO_FILUID },
- {"-o", TO_OPTION },
- {"-p", TO_FILFIFO },
- {"-r", TO_FILRD },
- {"-s", TO_FILGZ },
- {"-S", TO_FILSOCK },
- {"-t", TO_FILTT },
- {"-u", TO_FILSETU },
- {"-w", TO_FILWR },
- {"-x", TO_FILEX },
- {"-z", TO_STZER },
- {"", TO_NONOP }
- };
-static const struct t_op b_ops [] = {
- {"=", TO_STEQL },
-#ifdef KSH
- {"==", TO_STEQL },
-#endif /* KSH */
- {"!=", TO_STNEQ },
- {"<", TO_STLT },
- {">", TO_STGT },
- {"-eq", TO_INTEQ },
- {"-ne", TO_INTNE },
- {"-gt", TO_INTGT },
- {"-ge", TO_INTGE },
- {"-lt", TO_INTLT },
- {"-le", TO_INTLE },
- {"-ef", TO_FILEQ },
- {"-nt", TO_FILNT },
- {"-ot", TO_FILOT },
- {"", TO_NONOP }
- };
-
-static int test_stat ARGS((const char *path, struct stat *statb));
-static int test_eaccess ARGS((const char *path, int mode));
-static int test_oexpr ARGS((Test_env *te, int do_eval));
-static int test_aexpr ARGS((Test_env *te, int do_eval));
-static int test_nexpr ARGS((Test_env *te, int do_eval));
-static int test_primary ARGS((Test_env *te, int do_eval));
-static int ptest_isa ARGS((Test_env *te, Test_meta meta));
-static const char *ptest_getopnd ARGS((Test_env *te, Test_op op, int do_eval));
-static int ptest_eval ARGS((Test_env *te, Test_op op, const char *opnd1,
- const char *opnd2, int do_eval));
-static void ptest_error ARGS((Test_env *te, int offset, const char *msg));
-
-int
-c_test(wp)
- char **wp;
-{
- int argc;
- int res;
- Test_env te;
-
- te.flags = 0;
- te.isa = ptest_isa;
- te.getopnd = ptest_getopnd;
- te.eval = ptest_eval;
- te.error = ptest_error;
-
- for (argc = 0; wp[argc]; argc++)
- ;
-
- if (strcmp(wp[0], "[") == 0) {
- if (strcmp(wp[--argc], "]") != 0) {
- bi_errorf("missing ]");
- return T_ERR_EXIT;
- }
- }
-
- te.pos.wp = wp + 1;
- te.wp_end = wp + argc;
-
- /*
- * Handle the special cases from POSIX.2, section 4.62.4.
- * Implementation of all the rules isn't necessary since
- * our parser does the right thing for the ommited steps.
- */
- if (argc <= 5) {
- char **owp = wp;
- int invert = 0;
- Test_op op;
- const char *opnd1, *opnd2;
-
- while (--argc >= 0) {
- if ((*te.isa)(&te, TM_END))
- return !0;
- if (argc == 3) {
- opnd1 = (*te.getopnd)(&te, TO_NONOP, 1);
- if ((op = (Test_op) (*te.isa)(&te, TM_BINOP))) {
- opnd2 = (*te.getopnd)(&te, op, 1);
- res = (*te.eval)(&te, op, opnd1, opnd2,
- 1);
- if (te.flags & TEF_ERROR)
- return T_ERR_EXIT;
- if (invert & 1)
- res = !res;
- return !res;
- }
- /* back up to opnd1 */
- te.pos.wp--;
- }
- if (argc == 1) {
- opnd1 = (*te.getopnd)(&te, TO_NONOP, 1);
- res = (*te.eval)(&te, TO_STNZE, opnd1,
- (char *) 0, 1);
- if (invert & 1)
- res = !res;
- return !res;
- }
- if ((*te.isa)(&te, TM_NOT)) {
- invert++;
- } else
- break;
- }
- te.pos.wp = owp + 1;
- }
-
- return test_parse(&te);
-}
-
-/*
- * Generic test routines.
- */
-
-Test_op
-test_isop(te, meta, s)
- Test_env *te;
- Test_meta meta;
- const char *s;
-{
- char sc1;
- const struct t_op *otab;
-
- otab = meta == TM_UNOP ? u_ops : b_ops;
- if (*s) {
- sc1 = s[1];
- for (; otab->op_text[0]; otab++)
- if (sc1 == otab->op_text[1]
- && strcmp(s, otab->op_text) == 0
- && ((te->flags & TEF_DBRACKET)
- || (otab->op_num != TO_STLT
- && otab->op_num != TO_STGT)))
- return otab->op_num;
- }
- return TO_NONOP;
-}
-
-int
-test_eval(te, op, opnd1, opnd2, do_eval)
- Test_env *te;
- Test_op op;
- const char *opnd1;
- const char *opnd2;
- int do_eval;
-{
- int res;
- int not;
- struct stat b1, b2;
-
- if (!do_eval)
- return 0;
-
- switch ((int) op) {
- /*
- * Unary Operators
- */
- case TO_STNZE: /* -n */
- return *opnd1 != '\0';
- case TO_STZER: /* -z */
- return *opnd1 == '\0';
- case TO_OPTION: /* -o */
- if ((not = *opnd1 == '!'))
- opnd1++;
- if ((res = option(opnd1)) < 0)
- res = 0;
- else {
- res = Flag(res);
- if (not)
- res = !res;
- }
- return res;
- case TO_FILRD: /* -r */
- return test_eaccess(opnd1, R_OK) == 0;
- case TO_FILWR: /* -w */
- return test_eaccess(opnd1, W_OK) == 0;
- case TO_FILEX: /* -x */
- return test_eaccess(opnd1, X_OK) == 0;
- case TO_FILAXST: /* -a */
- return test_stat(opnd1, &b1) == 0;
- case TO_FILEXST: /* -e */
- /* at&t ksh does not appear to do the /dev/fd/ thing for
- * this (unless the os itself handles it)
- */
- return stat(opnd1, &b1) == 0;
- case TO_FILREG: /* -r */
- return test_stat(opnd1, &b1) == 0 && S_ISREG(b1.st_mode);
- case TO_FILID: /* -d */
- return test_stat(opnd1, &b1) == 0 && S_ISDIR(b1.st_mode);
- case TO_FILCDEV: /* -c */
-#ifdef S_ISCHR
- return test_stat(opnd1, &b1) == 0 && S_ISCHR(b1.st_mode);
-#else
- return 0;
-#endif
- case TO_FILBDEV: /* -b */
-#ifdef S_ISBLK
- return test_stat(opnd1, &b1) == 0 && S_ISBLK(b1.st_mode);
-#else
- return 0;
-#endif
- case TO_FILFIFO: /* -p */
-#ifdef S_ISFIFO
- return test_stat(opnd1, &b1) == 0 && S_ISFIFO(b1.st_mode);
-#else
- return 0;
-#endif
- case TO_FILSYM: /* -h -L */
-#ifdef S_ISLNK
- return lstat(opnd1, &b1) == 0 && S_ISLNK(b1.st_mode);
-#else
- return 0;
-#endif
- case TO_FILSOCK: /* -S */
-#ifdef S_ISSOCK
- return test_stat(opnd1, &b1) == 0 && S_ISSOCK(b1.st_mode);
-#else
- return 0;
-#endif
- case TO_FILCDF:/* -H HP context dependent files (directories) */
-#ifdef S_ISCDF
- {
- /* Append a + to filename and check to see if result is a
- * setuid directory. CDF stuff in general is hookey, since
- * it breaks for the following sequence: echo hi > foo+;
- * mkdir foo; echo bye > foo/default; chmod u+s foo
- * (foo+ refers to the file with hi in it, there is no way
- * to get at the file with bye in it - please correct me if
- * I'm wrong about this).
- */
- int len = strlen(opnd1);
- char *p = str_nsave(opnd1, len + 1, ATEMP);
-
- p[len++] = '+';
- p[len] = '\0';
- return stat(p, &b1) == 0 && S_ISCDF(b1.st_mode);
- }
-#else
- return 0;
-#endif
- case TO_FILSETU: /* -u */
-#ifdef S_ISUID
- return test_stat(opnd1, &b1) == 0
- && (b1.st_mode & S_ISUID) == S_ISUID;
-#else
- return 0;
-#endif
- case TO_FILSETG: /* -g */
-#ifdef S_ISGID
- return test_stat(opnd1, &b1) == 0
- && (b1.st_mode & S_ISGID) == S_ISGID;
-#else
- return 0;
-#endif
- case TO_FILSTCK: /* -k */
- return test_stat(opnd1, &b1) == 0
- && (b1.st_mode & S_ISVTX) == S_ISVTX;
- case TO_FILGZ: /* -s */
- return test_stat(opnd1, &b1) == 0 && b1.st_size > 0L;
- case TO_FILTT: /* -t */
- if (opnd1 && !bi_getn(opnd1, &res)) {
- te->flags |= TEF_ERROR;
- res = 0;
- } else
- res = isatty(opnd1 ? res : 0);
- return res;
- case TO_FILUID: /* -O */
- return test_stat(opnd1, &b1) == 0 && b1.st_uid == geteuid();
- case TO_FILGID: /* -G */
- return test_stat(opnd1, &b1) == 0 && b1.st_gid == getegid();
- /*
- * Binary Operators
- */
- case TO_STEQL: /* = */
- if (te->flags & TEF_DBRACKET)
- return gmatch(opnd1, opnd2, FALSE);
- return strcmp(opnd1, opnd2) == 0;
- case TO_STNEQ: /* != */
- if (te->flags & TEF_DBRACKET)
- return !gmatch(opnd1, opnd2, FALSE);
- return strcmp(opnd1, opnd2) != 0;
- case TO_STLT: /* < */
- return strcmp(opnd1, opnd2) < 0;
- case TO_STGT: /* > */
- return strcmp(opnd1, opnd2) > 0;
- case TO_INTEQ: /* -eq */
- case TO_INTNE: /* -ne */
- case TO_INTGE: /* -ge */
- case TO_INTGT: /* -gt */
- case TO_INTLE: /* -le */
- case TO_INTLT: /* -lt */
- {
- long v1, v2;
-
- if (!evaluate(opnd1, &v1, TRUE)
- || !evaluate(opnd2, &v2, TRUE))
- {
- /* error already printed.. */
- te->flags |= TEF_ERROR;
- return 1;
- }
- switch ((int) op) {
- case TO_INTEQ:
- return v1 == v2;
- case TO_INTNE:
- return v1 != v2;
- case TO_INTGE:
- return v1 >= v2;
- case TO_INTGT:
- return v1 > v2;
- case TO_INTLE:
- return v1 <= v2;
- case TO_INTLT:
- return v1 < v2;
- }
- }
- case TO_FILNT: /* -nt */
- return stat (opnd1, &b1) == 0 && stat (opnd2, &b2) == 0
- && b1.st_mtime > b2.st_mtime;
- case TO_FILOT: /* -ot */
- return stat (opnd1, &b1) == 0 && stat (opnd2, &b2) == 0
- && b1.st_mtime < b2.st_mtime;
- case TO_FILEQ: /* -ef */
- return stat (opnd1, &b1) == 0 && stat (opnd2, &b2) == 0
- && b1.st_dev == b2.st_dev
- && b1.st_ino == b2.st_ino;
- }
- (*te->error)(te, 0, "internal error: unknown op");
- return 1;
-}
-
-/* Nasty kludge to handle Korn's bizarre /dev/fd hack */
-static int
-test_stat(path, statb)
- const char *path;
- struct stat *statb;
-{
-#if !defined(HAVE_DEV_FD)
- int fd;
-
- if (strncmp(path, "/dev/fd/", 8) == 0 && getn(path + 8, &fd))
- return fstat(fd, statb);
-#endif /* !HAVE_DEV_FD */
-
- return stat(path, statb);
-}
-
-/* Another nasty kludge to handle Korn's bizarre /dev/fd hack */
-static int
-test_eaccess(path, mode)
- const char *path;
- int mode;
-{
-#if !defined(HAVE_DEV_FD)
- int fd;
-
- if (strncmp(path, "/dev/fd/", 8) == 0 && getn(path + 8, &fd)) {
- int flags;
-
- if ((flags = fcntl(fd, F_GETFL, 0)) < 0
- || (mode & X_OK)
- || ((mode & W_OK) && (flags & O_ACCMODE) == O_RDONLY)
- || ((mode & R_OK) && (flags & O_ACCMODE) == O_WRONLY))
- return -1;
- return 0;
- }
-#endif /* !HAVE_DEV_FD */
-
- return eaccess(path, mode);
-}
-
-int
-test_parse(te)
- Test_env *te;
-{
- int res;
-
- res = test_oexpr(te, 1);
-
- if (!(te->flags & TEF_ERROR) && !(*te->isa)(te, TM_END))
- (*te->error)(te, 0, "unexpected operator/operand");
-
- return (te->flags & TEF_ERROR) ? T_ERR_EXIT : !res;
-}
-
-static int
-test_oexpr(te, do_eval)
- Test_env *te;
- int do_eval;
-{
- int res;
-
- res = test_aexpr(te, do_eval);
- if (res)
- do_eval = 0;
- if (!(te->flags & TEF_ERROR) && (*te->isa)(te, TM_OR))
- return test_oexpr(te, do_eval) || res;
- return res;
-}
-
-static int
-test_aexpr(te, do_eval)
- Test_env *te;
- int do_eval;
-{
- int res;
-
- res = test_nexpr(te, do_eval);
- if (!res)
- do_eval = 0;
- if (!(te->flags & TEF_ERROR) && (*te->isa)(te, TM_AND))
- return test_aexpr(te, do_eval) && res;
- return res;
-}
-
-static int
-test_nexpr(te, do_eval)
- Test_env *te;
- int do_eval;
-{
- if (!(te->flags & TEF_ERROR) && (*te->isa)(te, TM_NOT))
- return !test_nexpr(te, do_eval);
- return test_primary(te, do_eval);
-}
-
-static int
-test_primary(te, do_eval)
- Test_env *te;
- int do_eval;
-{
- const char *opnd1, *opnd2;
- int res;
- Test_op op;
-
- if (te->flags & TEF_ERROR)
- return 0;
- if ((*te->isa)(te, TM_OPAREN)) {
- res = test_oexpr(te, do_eval);
- if (te->flags & TEF_ERROR)
- return 0;
- if (!(*te->isa)(te, TM_CPAREN)) {
- (*te->error)(te, 0, "missing closing paren");
- return 0;
- }
- return res;
- }
- if ((op = (Test_op) (*te->isa)(te, TM_UNOP))) {
- /* unary expression */
- opnd1 = (*te->getopnd)(te, op, do_eval);
- if (!opnd1) {
- (*te->error)(te, -1, "missing argument");
- return 0;
- }
-
- return (*te->eval)(te, op, opnd1, (const char *) 0, do_eval);
- }
- opnd1 = (*te->getopnd)(te, TO_NONOP, do_eval);
- if (!opnd1) {
- (*te->error)(te, 0, "expression expected");
- return 0;
- }
- if ((op = (Test_op) (*te->isa)(te, TM_BINOP))) {
- /* binary expression */
- opnd2 = (*te->getopnd)(te, op, do_eval);
- if (!opnd2) {
- (*te->error)(te, -1, "missing second argument");
- return 0;
- }
-
- return (*te->eval)(te, op, opnd1, opnd2, do_eval);
- }
- if (te->flags & TEF_DBRACKET) {
- (*te->error)(te, -1, "missing expression operator");
- return 0;
- }
- return (*te->eval)(te, TO_STNZE, opnd1, (const char *) 0, do_eval);
-}
-
-/*
- * Plain test (test and [ .. ]) specific routines.
- */
-
-/* Test if the current token is a whatever. Accepts the current token if
- * it is. Returns 0 if it is not, non-zero if it is (in the case of
- * TM_UNOP and TM_BINOP, the returned value is a Test_op).
- */
-static int
-ptest_isa(te, meta)
- Test_env *te;
- Test_meta meta;
-{
- /* Order important - indexed by Test_meta values */
- static const char *const tokens[] = {
- "-o", "-a", "!", "(", ")"
- };
- int ret;
-
- if (te->pos.wp >= te->wp_end)
- return meta == TM_END;
-
- if (meta == TM_UNOP || meta == TM_BINOP)
- ret = (int) test_isop(te, meta, *te->pos.wp);
- else if (meta == TM_END)
- ret = 0;
- else
- ret = strcmp(*te->pos.wp, tokens[(int) meta]) == 0;
-
- /* Accept the token? */
- if (ret)
- te->pos.wp++;
-
- return ret;
-}
-
-static const char *
-ptest_getopnd(te, op, do_eval)
- Test_env *te;
- Test_op op;
- int do_eval;
-{
- if (te->pos.wp >= te->wp_end)
- return op == TO_FILTT ? "1" : (const char *) 0;
- return *te->pos.wp++;
-}
-
-static int
-ptest_eval(te, op, opnd1, opnd2, do_eval)
- Test_env *te;
- Test_op op;
- const char *opnd1;
- const char *opnd2;
- int do_eval;
-{
- return test_eval(te, op, opnd1, opnd2, do_eval);
-}
-
-static void
-ptest_error(te, offset, msg)
- Test_env *te;
- int offset;
- const char *msg;
-{
- const char *op = te->pos.wp + offset >= te->wp_end ?
- (const char *) 0 : te->pos.wp[offset];
-
- te->flags |= TEF_ERROR;
- if (op)
- bi_errorf("%s: %s", op, msg);
- else
- bi_errorf("%s", msg);
-}
diff --git a/bin/pdksh/c_test.h b/bin/pdksh/c_test.h
deleted file mode 100644
index 0caf40b3dfc..00000000000
--- a/bin/pdksh/c_test.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/* $OpenBSD: c_test.h,v 1.1 1996/08/14 06:19:10 downsj Exp $ */
-
-/* Various types of operations. Keeping things grouped nicely
- * (unary,binary) makes switch() statements more efficeint.
- */
-enum Test_op {
- TO_NONOP = 0, /* non-operator */
- /* unary operators */
- TO_STNZE, TO_STZER, TO_OPTION,
- TO_FILAXST,
- TO_FILEXST,
- TO_FILREG, TO_FILBDEV, TO_FILCDEV, TO_FILSYM, TO_FILFIFO, TO_FILSOCK,
- TO_FILCDF, TO_FILID, TO_FILGID, TO_FILSETG, TO_FILSTCK, TO_FILUID,
- TO_FILRD, TO_FILGZ, TO_FILTT, TO_FILSETU, TO_FILWR, TO_FILEX,
- /* binary operators */
- TO_STEQL, TO_STNEQ, TO_STLT, TO_STGT, TO_INTEQ, TO_INTNE, TO_INTGT,
- TO_INTGE, TO_INTLT, TO_INTLE, TO_FILEQ, TO_FILNT, TO_FILOT
-};
-typedef enum Test_op Test_op;
-
-/* Used by Test_env.isa() (order important - used to index *_tokens[] arrays) */
-enum Test_meta {
- TM_OR, /* -o or || */
- TM_AND, /* -a or && */
- TM_NOT, /* ! */
- TM_OPAREN, /* ( */
- TM_CPAREN, /* ) */
- TM_UNOP, /* unary operator */
- TM_BINOP, /* binary operator */
- TM_END /* end of input */
-};
-typedef enum Test_meta Test_meta;
-
-#define TEF_ERROR BIT(0) /* set if we've hit an error */
-#define TEF_DBRACKET BIT(1) /* set if [[ .. ]] test */
-
-typedef struct test_env Test_env;
-struct test_env {
- int flags; /* TEF_* */
- union {
- char **wp; /* used by ptest_* */
- XPtrV *av; /* used by dbtestp_* */
- } pos;
- char **wp_end; /* used by ptest_* */
- int (*isa) ARGS((Test_env *te, Test_meta meta));
- const char *(*getopnd) ARGS((Test_env *te, Test_op op, int do_eval));
- int (*eval) ARGS((Test_env *te, Test_op op, const char *opnd1,
- const char *opnd2, int do_eval));
- void (*error) ARGS((Test_env *te, int offset, const char *msg));
-};
-
-Test_op test_isop ARGS((Test_env *te, Test_meta meta, const char *s));
-int test_eval ARGS((Test_env *te, Test_op op, const char *opnd1,
- const char *opnd2, int do_eval));
-int test_parse ARGS((Test_env *te));
diff --git a/bin/pdksh/c_ulimit.c b/bin/pdksh/c_ulimit.c
deleted file mode 100644
index b96c10bf5b8..00000000000
--- a/bin/pdksh/c_ulimit.c
+++ /dev/null
@@ -1,257 +0,0 @@
-/* $OpenBSD: c_ulimit.c,v 1.3 1997/06/19 13:58:39 kstailey Exp $ */
-
-/*
- ulimit -- handle "ulimit" builtin
-
- Reworked to use getrusage() and ulimit() at once (as needed on
- some schizophenic systems, eg, HP-UX 9.01), made argument parsing
- conform to at&t ksh, added autoconf support. Michael Rendell, May, '94
-
- Eric Gisin, September 1988
- Adapted to PD KornShell. Removed AT&T code.
-
- last edit: 06-Jun-1987 D A Gwyn
-
- This started out as the BRL UNIX System V system call emulation
- for 4.nBSD, and was later extended by Doug Kingston to handle
- the extended 4.nBSD resource limits. It now includes the code
- that was originally under case SYSULIMIT in source file "xec.c".
-*/
-
-#include "sh.h"
-#include "ksh_time.h"
-#ifdef HAVE_SYS_RESOURCE_H
-# include <sys/resource.h>
-#endif /* HAVE_SYS_RESOURCE_H */
-#ifdef HAVE_ULIMIT_H
-# include <ulimit.h>
-#else /* HAVE_ULIMIT_H */
-# ifdef HAVE_ULIMIT
-extern long ulimit();
-# endif /* HAVE_ULIMIT */
-#endif /* HAVE_ULIMIT_H */
-
-#define SOFT 0x1
-#define HARD 0x2
-
-int
-c_ulimit(wp)
- char **wp;
-{
- static const struct limits {
- const char *name;
- enum { RLIMIT, ULIMIT } which;
- int gcmd; /* get command */
- int scmd; /* set command (or -1, if no set command) */
- int factor; /* multiply by to get rlim_{cur,max} values */
- char option;
- } limits[] = {
- /* Do not use options -H, -S or -a */
-#ifdef RLIMIT_CPU
- { "time(cpu-seconds)", RLIMIT, RLIMIT_CPU, RLIMIT_CPU, 1, 't' },
-#endif
-#ifdef RLIMIT_FSIZE
- { "file(blocks)", RLIMIT, RLIMIT_FSIZE, RLIMIT_FSIZE, 512, 'f' },
-#else /* RLIMIT_FSIZE */
-# ifdef UL_GETFSIZE /* x/open */
- { "file(blocks)", ULIMIT, UL_GETFSIZE, UL_SETFSIZE, 1, 'f' },
-# else /* UL_GETFSIZE */
-# ifdef UL_GFILLIM /* svr4/xenix */
- { "file(blocks)", ULIMIT, UL_GFILLIM, UL_SFILLIM, 1, 'f' },
-# else /* UL_GFILLIM */
- { "file(blocks)", ULIMIT, 1, 2, 1, 'f' },
-# endif /* UL_GFILLIM */
-# endif /* UL_GETFSIZE */
-#endif /* RLIMIT_FSIZE */
-#ifdef RLIMIT_CORE
- { "coredump(blocks)", RLIMIT, RLIMIT_CORE, RLIMIT_CORE, 512, 'c' },
-#endif
-#ifdef RLIMIT_DATA
- { "data(kbytes)", RLIMIT, RLIMIT_DATA, RLIMIT_DATA, 1024, 'd' },
-#endif
-#ifdef RLIMIT_STACK
- { "stack(kbytes)", RLIMIT, RLIMIT_STACK, RLIMIT_STACK, 1024, 's' },
-#endif
-#ifdef RLIMIT_MEMLOCK
- { "lockedmem(kbytes)", RLIMIT, RLIMIT_MEMLOCK, RLIMIT_MEMLOCK, 1024, 'l' },
-#endif
-#ifdef RLIMIT_RSS
- { "memory(kbytes)", RLIMIT, RLIMIT_RSS, RLIMIT_RSS, 1024, 'm' },
-#endif
-#ifdef RLIMIT_NOFILE
- { "nofiles(descriptors)", RLIMIT, RLIMIT_NOFILE, RLIMIT_NOFILE, 1, 'n' },
-#else /* RLIMIT_NOFILE */
-# ifdef UL_GDESLIM /* svr4/xenix */
- { "nofiles(descriptors)", ULIMIT, UL_GDESLIM, -1, 1, 'n' },
-# endif /* UL_GDESLIM */
-#endif /* RLIMIT_NOFILE */
-#ifdef RLIMIT_NPROC
- { "processes", RLIMIT, RLIMIT_NPROC, RLIMIT_NPROC, 1, 'p' },
-#endif
-#ifdef RLIMIT_VMEM
- { "vmemory(kbytes)", RLIMIT, RLIMIT_VMEM, RLIMIT_VMEM, 1024, 'v' },
-#else /* RLIMIT_VMEM */
- /* These are not quite right - really should subtract etext or something */
-# ifdef UL_GMEMLIM /* svr4/xenix */
- { "vmemory(maxaddr)", ULIMIT, UL_GMEMLIM, -1, 1, 'v' },
-# else /* UL_GMEMLIM */
-# ifdef UL_GETBREAK /* osf/1 */
- { "vmemory(maxaddr)", ULIMIT, UL_GETBREAK, -1, 1, 'v' },
-# else /* UL_GETBREAK */
-# ifdef UL_GETMAXBRK /* hpux */
- { "vmemory(maxaddr)", ULIMIT, UL_GETMAXBRK, -1, 1, 'v' },
-# endif /* UL_GETMAXBRK */
-# endif /* UL_GETBREAK */
-# endif /* UL_GMEMLIM */
-#endif /* RLIMIT_VMEM */
-#ifdef RLIMIT_SWAP
- { "swap(kbytes)", RLIMIT_SWAP, RLIMIT_SWAP, 1024, 'w' },
-#endif
- { (char *) 0 }
- };
- static char options[3 + NELEM(limits)];
- rlim_t UNINITIALIZED(val);
- int how = SOFT | HARD;
- const struct limits *l;
- int set, all = 0;
- int optc, what;
-#ifdef HAVE_SETRLIMIT
- struct rlimit limit;
-#endif /* HAVE_SETRLIMIT */
-
- if (!options[0]) {
- /* build options string on first call - yuck */
- char *p = options;
-
- *p++ = 'H'; *p++ = 'S'; *p++ = 'a';
- for (l = limits; l->name; l++)
- *p++ = l->option;
- *p = '\0';
- }
- what = 'f';
- while ((optc = ksh_getopt(wp, &builtin_opt, options)) != EOF)
- switch (optc) {
- case 'H':
- how = HARD;
- break;
- case 'S':
- how = SOFT;
- break;
- case 'a':
- all = 1;
- break;
- case '?':
- return 1;
- default:
- what = optc;
- }
-
- for (l = limits; l->name && l->option != what; l++)
- ;
- if (!l->name) {
- internal_errorf(0, "ulimit: %c", what);
- return 1;
- }
-
- wp += builtin_opt.optind;
- set = *wp ? 1 : 0;
- if (set) {
- char *p = *wp;
-
- if (all || wp[1]) {
- bi_errorf("too many arguments");
- return 1;
- }
-#ifdef RLIM_INFINITY
- if (strcmp(p, "unlimited") == 0)
- val = RLIM_INFINITY;
- else
-#endif /* RLIM_INFINITY */
- {
- long rval;
-
- if (!evaluate(p, &rval, TRUE))
- return 1;
- val = rval * l->factor;
- }
- }
- if (all) {
- for (l = limits; l->name; l++) {
-#ifdef HAVE_SETRLIMIT
- if (l->which == RLIMIT) {
- getrlimit(l->gcmd, &limit);
- if (how & SOFT)
- val = limit.rlim_cur;
- else if (how & HARD)
- val = limit.rlim_max;
- } else
-#endif /* HAVE_SETRLIMIT */
-#ifdef HAVE_ULIMIT
- {
- val = ulimit(l->gcmd, (rlim_t) 0);
- }
-#else /* HAVE_ULIMIT */
- ;
-#endif /* HAVE_ULIMIT */
- shprintf("%-20s ", l->name);
-#ifdef RLIM_INFINITY
- if (val == RLIM_INFINITY)
- shprintf("unlimited\n");
- else
-#endif /* RLIM_INFINITY */
- {
- val /= l->factor;
- shprintf("%ld\n", (long) val);
- }
- }
- return 0;
- }
-#ifdef HAVE_SETRLIMIT
- if (l->which == RLIMIT) {
- getrlimit(l->gcmd, &limit);
- if (set) {
- if (how & SOFT)
- limit.rlim_cur = val;
- if (how & HARD)
- limit.rlim_max = val;
- if (setrlimit(l->scmd, &limit) < 0) {
- bi_errorf("bad limit: %s", strerror(errno));
- return 1;
- }
- } else {
- if (how & SOFT)
- val = limit.rlim_cur;
- else if (how & HARD)
- val = limit.rlim_max;
- }
- } else
-#endif /* HAVE_SETRLIMIT */
-#ifdef HAVE_ULIMIT
- {
- if (set) {
- if (l->scmd == -1) {
- bi_errorf("can't change limit");
- return 1;
- } else if (ulimit(l->scmd, val) < 0) {
- bi_errorf("bad limit: %s", strerror(errno));
- return 1;
- }
- } else
- val = ulimit(l->gcmd, (rlim_t) 0);
- }
-#else /* HAVE_ULIMIT */
- ;
-#endif /* HAVE_ULIMIT */
- if (!set) {
-#ifdef RLIM_INFINITY
- if (val == RLIM_INFINITY)
- shprintf("unlimited\n");
- else
-#endif /* RLIM_INFINITY */
- {
- val /= l->factor;
- shprintf("%ld\n", (long) val);
- }
- }
- return 0;
-}
diff --git a/bin/pdksh/conf-end.h b/bin/pdksh/conf-end.h
deleted file mode 100644
index 8b65cb7d1df..00000000000
--- a/bin/pdksh/conf-end.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/* $OpenBSD: conf-end.h,v 1.2 1996/08/25 12:37:58 downsj Exp $ */
-
-/*
- * End of configuration stuff for PD ksh.
- */
-
-#if defined(EMACS) || defined(VI)
-# define EDIT
-#else
-# undef EDIT
-#endif
-
-/* Super small configuration-- no editing. */
-#if defined(EDIT) && defined(NOEDIT)
-# undef EDIT
-# undef EMACS
-# undef VI
-#endif
-
-/* Editing implies history */
-#if defined(EDIT) && !defined(HISTORY)
-# define HISTORY
-#endif /* EDIT */
-
-/*
- * if you don't have mmap() you can't use Peter Collinson's history
- * mechanism. If that is the case, then define EASY_HISTORY
- */
-#if defined(HISTORY) && (!defined(COMPLEX_HISTORY) || !defined(HAVE_MMAP) || !defined(HAVE_FLOCK))
-# undef COMPLEX_HISTORY
-# define EASY_HISTORY /* sjg's trivial history file */
-#endif
-
-/* Can we safely catch sigchld and wait for processes? */
-#if (defined(HAVE_WAITPID) || defined(HAVE_WAIT3)) \
- && (defined(POSIX_SIGNALS) || defined(BSD42_SIGNALS))
-# define JOB_SIGS
-#endif
-
-#if !defined(JOB_SIGS) || !(defined(POSIX_PGRP) || defined(BSD_PGRP))
-# undef JOBS /* if no JOB_SIGS, no job control support */
-#endif
-
-/* pdksh assumes system calls return EINTR if a signal happened (this so
- * the signal handler doesn't have to longjmp()). I don't know if this
- * happens (or can be made to happen) with sigset() et. al. (the bsd41 signal
- * routines), so, the autoconf stuff checks what they do and defines
- * SIGNALS_DONT_INTERRUPT if signals don't interrupt read().
- * If SIGNALS_DONT_INTERRUPT isn't defined and your compiler chokes on this,
- * delete the hash in front of the error (and file a bug report).
- */
-#ifdef SIGNALS_DONT_INTERRUPT
- # error pdksh needs interruptable system calls.
-#endif /* SIGNALS_DONT_INTERRUPT */
-
-#ifdef HAVE_GCC_FUNC_ATTR
-# define GCC_FUNC_ATTR(x) __attribute__((x))
-# define GCC_FUNC_ATTR2(x,y) __attribute__((x,y))
-#else
-# define GCC_FUNC_ATTR(x)
-# define GCC_FUNC_ATTR2(x,y)
-#endif /* HAVE_GCC_FUNC_ATTR */
diff --git a/bin/pdksh/config.h b/bin/pdksh/config.h
deleted file mode 100644
index c949a254ee2..00000000000
--- a/bin/pdksh/config.h
+++ /dev/null
@@ -1,351 +0,0 @@
-/* $OpenBSD: config.h,v 1.2 1996/08/25 11:56:34 downsj Exp $ */
-
-/* config.h. Generated automatically by configure. */
-/* config.h.in. Generated automatically from configure.in by autoheader. */
-/*
- * This file, acconfig.h, which is a part of pdksh (the public domain ksh),
- * is placed in the public domain. It comes with no licence, warranty
- * or guarantee of any kind (i.e., at your own risk).
- */
-
-#ifndef CONFIG_H
-#define CONFIG_H
-
-
-/* Define if on AIX 3.
- System headers sometimes define this.
- We just want to avoid a redefinition error message. */
-#ifndef _ALL_SOURCE
-/* #undef _ALL_SOURCE */
-#endif
-
-/* Define if the closedir function returns void instead of int. */
-/* #undef CLOSEDIR_VOID */
-
-/* Define to empty if the keyword does not work. */
-/* #undef const */
-
-
-/* Define to `int' if <sys/types.h> doesn't define. */
-/* #undef gid_t */
-
-/* Define if you have a working `mmap' system call. */
-#define HAVE_MMAP 1
-
-/* Define if your struct stat has st_rdev. */
-#define HAVE_ST_RDEV 1
-
-/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
-#define HAVE_SYS_WAIT_H 1
-
-/* Define if you have <unistd.h>. */
-#define HAVE_UNISTD_H 1
-
-/* Define if on MINIX. */
-/* #undef _MINIX */
-
-/* Define to `int' if <sys/types.h> doesn't define. */
-/* #undef mode_t */
-
-/* Define to `long' if <sys/types.h> doesn't define. */
-/* #undef off_t */
-
-/* Define to `int' if <sys/types.h> doesn't define. */
-/* #undef pid_t */
-
-/* Define if the system does not provide POSIX.1 features except
- with this defined. */
-/* #undef _POSIX_1_SOURCE */
-
-/* Define if you need to in order for stat and other things to work. */
-/* #undef _POSIX_SOURCE */
-
-/* Define as the return type of signal handlers (int or void). */
-#define RETSIGTYPE void
-
-/* Define if the `S_IS*' macros in <sys/stat.h> do not work properly. */
-/* #undef STAT_MACROS_BROKEN */
-
-/* Define if `sys_siglist' is declared by <signal.h>. */
-#define SYS_SIGLIST_DECLARED 1
-
-/* Define if you can safely include both <sys/time.h> and <time.h>. */
-#define TIME_WITH_SYS_TIME 1
-
-/* Define to `int' if <sys/types.h> doesn't define. */
-/* #undef uid_t */
-
-/* Define if the closedir function returns void instead of int. */
-/* #undef VOID_CLOSEDIR */
-
-/* Define if your kernal doesn't handle scripts starting with #! */
-/* #undef SHARPBANG */
-
-/* Define if dup2() preserves the close-on-exec flag (ultrix does this) */
-/* #undef DUP2_BROKEN */
-
-/* Define as the return value of signal handlers (0 or ). */
-#define RETSIGVAL
-
-/* Define if you have posix signal routines (sigaction(), et. al.) */
-#define POSIX_SIGNALS 1
-
-/* Define if you have BSD4.2 signal routines (sigsetmask(), et. al.) */
-/* #undef BSD42_SIGNALS */
-
-/* Define if you have BSD4.1 signal routines (sigset(), et. al.) */
-/* #undef BSD41_SIGNALS */
-
-/* Define if you have v7 signal routines (signal(), signal reset on delivery) */
-/* #undef V7_SIGNALS */
-
-/* Define to use the fake posix signal routines (sigact.[ch]) */
-/* #undef USE_FAKE_SIGACT */
-
-/* Define if signals don't interrupt read() */
-/* #undef SIGNALS_DONT_INTERRUPT */
-
-/* Define if you have bsd versions of the setpgrp() and getpgrp() routines */
-/* #undef BSD_PGRP */
-
-/* Define if you have POSIX versions of the setpgid() and getpgrp() routines */
-#define POSIX_PGRP 1
-
-/* Define if you have sysV versions of the setpgrp() and getpgrp() routines */
-/* #undef SYSV_PGRP */
-
-/* Define if you don't have setpgrp(), setpgid() or getpgrp() routines */
-/* #undef NO_PGRP */
-
-/* Define to char if your compiler doesn't like the void keyword */
-/* #undef void */
-
-/* Define to nothing if compiler doesn't like the volatile keyword */
-/* #undef volatile */
-
-/* Define if C compiler groks function prototypes */
-#define HAVE_PROTOTYPES 1
-
-/* Define if C compiler groks __attribute__((...)) (const, noreturn, format) */
-#define HAVE_GCC_FUNC_ATTR 1
-
-/* Define to 32-bit signed integer type if <sys/types.h> doesn't define */
-/* #undef clock_t */
-
-/* Define to the type of struct rlimit fields if the rlim_t type is missing */
-/* #undef rlim_t */
-
-/* Define if time() is declared in <time.h> */
-#define TIME_DECLARED 1
-
-/* Define to `unsigned' if <signal.h> doesn't define */
-/* #undef sigset_t */
-
-/* Define if sys_errlist[] and sys_nerr are in the C library */
-#define HAVE_SYS_ERRLIST 1
-
-/* Define if sys_errlist[] and sys_nerr are defined in <errno.h> */
-#define SYS_ERRLIST_DECLARED 1
-
-/* Define if sys_siglist[] is in the C library */
-#define HAVE_SYS_SIGLIST 1
-
-/* Define if you have a sane <termios.h> header file */
-#define HAVE_TERMIOS_H 1
-
-/* Define if you have a memset() function in your C library */
-#define HAVE_MEMSET 1
-
-/* Define if you have a memmove() function in your C library */
-#define HAVE_MEMMOVE 1
-
-/* Define if you have a bcopy() function in your C library */
-/* #undef HAVE_BCOPY */
-
-/* Define if you have a lstat() function in your C library */
-#define HAVE_LSTAT 1
-
-/* Define if you have a sane <termio.h> header file */
-/* #undef HAVE_TERMIO_H */
-
-/* Define if you don't have times() or if it always returns 0 */
-/* #undef TIMES_BROKEN */
-
-/* Define if opendir() will open non-directory files */
-/* #undef OPENDIR_DOES_NONDIR */
-
-/* Define if the pgrp of setpgrp() can't be the pid of a zombie process */
-/* #undef NEED_PGRP_SYNC */
-
-/* Define if you arg running SCO unix */
-/* #undef OS_SCO */
-
-/* Define if you arg running ISC unix */
-/* #undef OS_ISC */
-
-/* Define if you arg running OS2 with the EMX library */
-/* #undef OS2 */
-
-/* Define if you have a POSIX.1 compatiable <sys/wait.h> */
-#define POSIX_SYS_WAIT 1
-
-/* Define if your OS maps references to /dev/fd/n to file descriptor n */
-#define HAVE_DEV_FD 1
-
-/* Default PATH (see comments in configure.in for more details) */
-#define DEFAULT_PATH "/bin:/usr/bin:/usr/ucb"
-
-/* Include ksh features? (see comments in configure.in for more details) */
-/* #define KSH 1 */
-
-/* Include emacs editing? (see comments in configure.in for more details) */
-#define EMACS 1
-
-/* Include vi editing? (see comments in configure.in for more details) */
-#define VI 1
-
-/* Include job control? (see comments in configure.in for more details) */
-#define JOBS 1
-
-/* Include brace-expansion? (see comments in configure.in for more details) */
-#define BRACE_EXPAND 1
-
-/* Include any history? (see comments in configure.in for more details) */
-#define HISTORY 1
-
-/* Include complex history? (see comments in configure.in for more details) */
-/* #undef COMPLEX_HISTORY */
-
-/* Strict POSIX behaviour? (see comments in configure.in for more details) */
-/* #undef POSIXLY_CORRECT */
-
-/* Specify default $ENV? (see comments in configure.in for more details) */
-/* #undef DEFAULT_ENV */
-
-/* Include shl(1) support? (see comments in configure.in for more details) */
-/* #undef SWTCH */
-
-/* Include game-of-life? (see comments in configure.in for more details) */
-/* #undef SILLY */
-
-/* The number of bytes in a int. */
-#define SIZEOF_INT 4
-
-/* The number of bytes in a long. */
-#if defined(alpha)
-#define SIZEOF_LONG 8
-#else
-#define SIZEOF_LONG 4
-#endif
-
-/* Define if you have the _setjmp function. */
-/* #undef HAVE__SETJMP */
-
-/* Define if you have the confstr function. */
-#define HAVE_CONFSTR 1
-
-/* Define if you have the flock function. */
-#define HAVE_FLOCK 1
-
-/* Define if you have the getgroups function. */
-/* #undef HAVE_GETGROUPS */
-
-/* Define if you have the getrusage function. */
-/* #undef HAVE_GETRUSAGE */
-
-/* Define if you have the getwd function. */
-#define HAVE_GETWD 1
-
-/* Define if you have the killpg function. */
-#define HAVE_KILLPG 1
-
-/* Define if you have the nice function. */
-#define HAVE_NICE 1
-
-/* Define if you have the setrlimit function. */
-#define HAVE_SETRLIMIT 1
-
-/* Define if you have the sigsetjmp function. */
-#define HAVE_SIGSETJMP 1
-
-/* Define if you have the strcasecmp function. */
-#define HAVE_STRCASECMP 1
-
-/* Define if you have the strerror function. */
-#define HAVE_STRERROR 1
-
-/* Define if you have the strstr function. */
-#define HAVE_STRSTR 1
-
-/* Define if you have the sysconf function. */
-#define HAVE_SYSCONF 1
-
-/* Define if you have the tcsetpgrp function. */
-#define HAVE_TCSETPGRP 1
-
-/* Define if you have the ulimit function. */
-/* #undef HAVE_ULIMIT */
-
-/* Define if you have the wait3 function. */
-#define HAVE_WAIT3 1
-
-/* Define if you have the waitpid function. */
-#define HAVE_WAITPID 1
-
-/* Define if you have the <dirent.h> header file. */
-#define HAVE_DIRENT_H 1
-
-/* Define if you have the <fcntl.h> header file. */
-#define HAVE_FCNTL_H 1
-
-/* Define if you have the <limits.h> header file. */
-#define HAVE_LIMITS_H 1
-
-/* Define if you have the <memory.h> header file. */
-#define HAVE_MEMORY_H 1
-
-/* Define if you have the <ndir.h> header file. */
-/* #undef HAVE_NDIR_H */
-
-/* Define if you have the <paths.h> header file. */
-#define HAVE_PATHS_H 1
-
-/* Define if you have the <stddef.h> header file. */
-#define HAVE_STDDEF_H 1
-
-/* Define if you have the <stdlib.h> header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define if you have the <string.h> header file. */
-#define HAVE_STRING_H 1
-
-/* Define if you have the <sys/dir.h> header file. */
-/* #undef HAVE_SYS_DIR_H */
-
-/* Define if you have the <sys/ndir.h> header file. */
-/* #undef HAVE_SYS_NDIR_H */
-
-/* Define if you have the <sys/param.h> header file. */
-#define HAVE_SYS_PARAM_H 1
-
-/* Define if you have the <sys/resource.h> header file. */
-#define HAVE_SYS_RESOURCE_H 1
-
-/* Define if you have the <sys/time.h> header file. */
-#define HAVE_SYS_TIME_H 1
-
-/* Define if you have the <sys/wait.h> header file. */
-#define HAVE_SYS_WAIT_H 1
-
-/* Define if you have the <ulimit.h> header file. */
-/* #undef HAVE_ULIMIT_H */
-
-/* Define if you have the <values.h> header file. */
-/* #undef HAVE_VALUES_H */
-
-/* Need to use a separate file to keep the configure script from commenting
- * out the undefs....
- */
-#include "conf-end.h"
-
-#endif /* CONFIG_H */
diff --git a/bin/pdksh/edit.c b/bin/pdksh/edit.c
deleted file mode 100644
index 2d4b96b4d0f..00000000000
--- a/bin/pdksh/edit.c
+++ /dev/null
@@ -1,1013 +0,0 @@
-/* $OpenBSD: edit.c,v 1.6 1997/06/19 13:58:39 kstailey Exp $ */
-
-/*
- * Command line editing - common code
- *
- */
-
-#include "config.h"
-#ifdef EDIT
-
-#include "sh.h"
-#include "tty.h"
-#define EXTERN
-#include "edit.h"
-#undef EXTERN
-#ifdef OS_SCO /* SCO Unix 3.2v4.1 */
-# include <sys/stream.h> /* needed for <sys/ptem.h> */
-# include <sys/ptem.h> /* needed for struct winsize */
-#endif /* OS_SCO */
-#include <sys/ioctl.h>
-#include <ctype.h>
-#include "ksh_stat.h"
-
-
-#if defined(TIOCGWINSZ)
-static RETSIGTYPE x_sigwinch ARGS((int sig));
-static int got_sigwinch;
-static void check_sigwinch ARGS((void));
-#endif /* TIOCGWINSZ */
-
-static int x_file_glob ARGS((int flags, const char *str, int slen,
- char ***wordsp));
-static int x_command_glob ARGS((int flags, const char *str, int slen,
- char ***wordsp));
-static int x_locate_word ARGS((const char *buf, int buflen, int pos,
- int *startp, int *is_command));
-
-static char vdisable_c;
-
-
-/* Called from main */
-void
-x_init()
-{
- /* set to -1 to force initial binding */
- edchars.erase = edchars.kill = edchars.intr = edchars.quit
- = edchars.eof = -1;
- /* default value for deficient systems */
- edchars.werase = 027; /* ^W */
-
-#ifdef TIOCGWINSZ
-# ifdef SIGWINCH
- if (setsig(&sigtraps[SIGWINCH], x_sigwinch, SS_RESTORE_ORIG|SS_SHTRAP))
- sigtraps[SIGWINCH].flags |= TF_SHELL_USES;
-# endif /* SIGWINCH */
- got_sigwinch = 1; /* force initial check */
- check_sigwinch();
-#endif /* TIOCGWINSZ */
-
-#ifdef EMACS
- x_init_emacs();
-#endif /* EMACS */
-
- /* Bizarreness to figure out how to disable
- * a struct termios.c_cc[] char
- */
-#ifdef _POSIX_VDISABLE
- if (_POSIX_VDISABLE >= 0)
- vdisable_c = (char) _POSIX_VDISABLE;
- else
- /* `feature not available' */
- vdisable_c = (char) 0377;
-#else
-# if defined(HAVE_PATHCONF) && defined(_PC_VDISABLE)
- vdisable_c = fpathconf(tty_fd, _PC_VDISABLE);
-# else
- vdisable_c = (char) 0377; /* default to old BSD value */
-# endif
-#endif /* _POSIX_VDISABLE */
-}
-
-#if defined(TIOCGWINSZ)
-static RETSIGTYPE
-x_sigwinch(sig)
- int sig;
-{
- got_sigwinch = 1;
- return RETSIGVAL;
-}
-
-static void
-check_sigwinch ARGS((void))
-{
- if (got_sigwinch) {
- struct winsize ws;
-
- got_sigwinch = 0;
- if (procpid == kshpid && ioctl(tty_fd, TIOCGWINSZ, &ws) >= 0) {
- struct tbl *vp;
-
- /* Do NOT export COLUMNS/LINES. Many applications
- * check COLUMNS/LINES before checking ws.ws_col/row,
- * so if the app is started with C/L in the environ
- * and the window is then resized, the app won't
- * see the change cause the environ doesn't change.
- */
- if (ws.ws_col) {
- x_cols = ws.ws_col < MIN_COLS ? MIN_COLS
- : ws.ws_col;
-
- if ((vp = typeset("COLUMNS", 0, 0, 0, 0)))
- setint(vp, (long) ws.ws_col);
- }
- if (ws.ws_row
- && (vp = typeset("LINES", 0, 0, 0, 0)))
- setint(vp, (long) ws.ws_row);
- }
- }
-}
-#endif /* TIOCGWINSZ */
-
-/*
- * read an edited command line
- */
-int
-x_read(buf, len)
- char *buf;
- size_t len;
-{
- int i;
-
-#if defined(TIOCGWINSZ)
- if (got_sigwinch)
- check_sigwinch();
-#endif /* TIOCGWINSZ */
-
- x_mode(TRUE);
-#ifdef EMACS
- if (Flag(FEMACS) || Flag(FGMACS))
- i = x_emacs(buf, len);
- else
-#endif
-#ifdef VI
- if (Flag(FVI))
- i = x_vi(buf, len);
- else
-#endif
- i = -1; /* internal error */
- x_mode(FALSE);
- return i;
-}
-
-/* tty I/O */
-
-int
-x_getc()
-{
-#ifdef OS2
- unsigned char c = _read_kbd(0, 1, 0);
- return c == 0 ? 0xE0 : c;
-#else /* OS2 */
- char c;
- int n;
-
- while ((n = blocking_read(0, &c, 1)) < 0 && errno == EINTR)
- if (trap) {
- x_mode(FALSE);
- runtraps(0);
- x_mode(TRUE);
- }
- if (n != 1)
- return -1;
- return (int) (unsigned char) c;
-#endif /* OS2 */
-}
-
-void
-x_flush()
-{
- shf_flush(shl_out);
-}
-
-void
-x_putc(c)
- int c;
-{
- shf_putc(c, shl_out);
-}
-
-void
-x_puts(s)
- const char *s;
-{
- while (*s != 0)
- shf_putc(*s++, shl_out);
-}
-
-bool_t
-x_mode(onoff)
- bool_t onoff;
-{
- static bool_t x_cur_mode;
- bool_t prev;
-
- if (x_cur_mode == onoff)
- return x_cur_mode;
- prev = x_cur_mode;
- x_cur_mode = onoff;
-
- if (onoff) {
- TTY_state cb;
- X_chars oldchars;
-
- oldchars = edchars;
- cb = tty_state;
-
-#if defined(HAVE_TERMIOS_H) || defined(HAVE_TERMIO_H)
- edchars.erase = cb.c_cc[VERASE];
- edchars.kill = cb.c_cc[VKILL];
- edchars.intr = cb.c_cc[VINTR];
- edchars.quit = cb.c_cc[VQUIT];
- edchars.eof = cb.c_cc[VEOF];
-# ifdef VWERASE
- edchars.werase = cb.c_cc[VWERASE];
-# endif
-# ifdef _CRAY2 /* brain-damaged terminal handler */
- cb.c_lflag &= ~(ICANON|ECHO);
- /* rely on print routine to map '\n' to CR,LF */
-# else
- cb.c_iflag &= ~(INLCR|ICRNL);
-# ifdef _BSD_SYSV /* need to force CBREAK instead of RAW (need CRMOD on output) */
- cb.c_lflag &= ~(ICANON|ECHO);
-# else
-# ifdef SWTCH /* need CBREAK to handle swtch char */
- cb.c_lflag &= ~(ICANON|ECHO);
- cb.c_lflag |= ISIG;
- cb.c_cc[VINTR] = vdisable_c;
- cb.c_cc[VQUIT] = vdisable_c;
-# else
- cb.c_lflag &= ~(ISIG|ICANON|ECHO);
-# endif
-# endif
-# ifdef VLNEXT
- /* osf/1 processes lnext when ~icanon */
- cb.c_cc[VLNEXT] = vdisable_c;
-# endif /* VLNEXT */
-# ifdef VDISCARD
- /* sunos 4.1.x & osf/1 processes discard(flush) when ~icanon */
- cb.c_cc[VDISCARD] = vdisable_c;
-# endif /* VDISCARD */
- cb.c_cc[VTIME] = 0;
- cb.c_cc[VMIN] = 1;
-# endif /* _CRAY2 */
-#else
- /* Assume BSD tty stuff. */
- edchars.erase = cb.sgttyb.sg_erase;
- edchars.kill = cb.sgttyb.sg_kill;
- cb.sgttyb.sg_flags &= ~ECHO;
- cb.sgttyb.sg_flags |= CBREAK;
-# ifdef TIOCGATC
- edchars.intr = cb.lchars.tc_intrc;
- edchars.quit = cb.lchars.tc_quitc;
- edchars.eof = cb.lchars.tc_eofc;
- edchars.werase = cb.lchars.tc_werasc;
- cb.lchars.tc_suspc = -1;
- cb.lchars.tc_dsuspc = -1;
- cb.lchars.tc_lnextc = -1;
- cb.lchars.tc_statc = -1;
- cb.lchars.tc_intrc = -1;
- cb.lchars.tc_quitc = -1;
- cb.lchars.tc_rprntc = -1;
-# else
- edchars.intr = cb.tchars.t_intrc;
- edchars.quit = cb.tchars.t_quitc;
- edchars.eof = cb.tchars.t_eofc;
- cb.tchars.t_intrc = -1;
- cb.tchars.t_quitc = -1;
-# ifdef TIOCGLTC
- edchars.werase = cb.ltchars.t_werasc;
- cb.ltchars.t_suspc = -1;
- cb.ltchars.t_dsuspc = -1;
- cb.ltchars.t_lnextc = -1;
- cb.ltchars.t_rprntc = -1;
-# endif
-# endif /* TIOCGATC */
-#endif /* HAVE_TERMIOS_H || HAVE_TERMIO_H */
-
- set_tty(tty_fd, &cb, TF_WAIT);
-
- if (memcmp(&edchars, &oldchars, sizeof(edchars)) != 0) {
-#ifdef EMACS
- x_emacs_keys(&edchars);
-#endif
- }
- } else
- /* TF_WAIT doesn't seem to be necessary when leaving xmode */
- set_tty(tty_fd, &tty_state, TF_NONE);
-
- return prev;
-}
-
-/* NAME:
- * promptlen - calculate the length of PS1 etc.
- *
- * DESCRIPTION:
- * This function is based on a fix from guy@demon.co.uk
- * It fixes a bug in that if PS1 contains '!', the length
- * given by strlen() is probably wrong.
- *
- * RETURN VALUE:
- * length
- */
-int
-promptlen(cp, spp)
- const char *cp;
- const char **spp;
-{
- int count = 0;
- const char *sp = cp;
- char delimiter = 0;
- int indelimit = 0;
-
- /* Undocumented AT&T ksh feature:
- * If the second char in the prompt string is \r then the first char
- * is taken to be a non-printing delimiter and any chars between two
- * instances of the delimiter are not considered to be part of the
- * prompt length
- */
- if (*cp && cp[1] == '\r') {
- delimiter = *cp;
- cp += 2;
- }
-
- for (; *cp; cp++) {
- if (indelimit && *cp != delimiter)
- ;
- else if (*cp == '\n' || *cp == '\r') {
- count = 0;
- sp = cp + 1;
- } else if (*cp == '\t') {
- count = (count | 7) + 1;
- } else if (*cp == '\b') {
- if (count > 0)
- count--;
- } else if (*cp == delimiter)
- indelimit = !indelimit;
- else
- count++;
- }
- if (spp)
- *spp = sp;
- return count;
-}
-
-void
-set_editmode(ed)
- const char *ed;
-{
- static const enum sh_flag edit_flags[] = {
-#ifdef EMACS
- FEMACS, FGMACS,
-#endif
-#ifdef VI
- FVI,
-#endif
- };
- char *rcp;
- int i;
-
- if ((rcp = ksh_strrchr_dirsep(ed)))
- ed = ++rcp;
- for (i = 0; i < NELEM(edit_flags); i++)
- if (strstr(ed, options[(int) edit_flags[i]].name)) {
- change_flag(edit_flags[i], OF_SPECIAL, 1);
- return;
- }
-}
-
-/* ------------------------------------------------------------------------- */
-/* Misc common code for vi/emacs */
-
-/* Handle the commenting/uncommenting of a line.
- * Returns:
- * 1 if a carriage return is indicated (comment added)
- * 0 if no return (comment removed)
- * -1 if there is an error (not enough room for comment chars)
- * If successful, *lenp contains the new length. Note: cursor should be
- * moved to the start of the line after (un)commenting.
- */
-int
-x_do_comment(buf, bsize, lenp)
- char *buf;
- int bsize;
- int *lenp;
-{
- int i, j;
- int len = *lenp;
-
- if (len == 0)
- return 1; /* somewhat arbitrary - it's what at&t ksh does */
-
- /* Already commented? */
- if (buf[0] == '#') {
- int saw_nl = 0;
-
- for (j = 0, i = 1; i < len; i++) {
- if (!saw_nl || buf[i] != '#')
- buf[j++] = buf[i];
- saw_nl = buf[i] == '\n';
- }
- *lenp = j;
- return 0;
- } else {
- int n = 1;
-
- /* See if there's room for the #'s - 1 per \n */
- for (i = 0; i < len; i++)
- if (buf[i] == '\n')
- n++;
- if (len + n >= bsize)
- return -1;
- /* Now add them... */
- for (i = len, j = len + n; --i >= 0; ) {
- if (buf[i] == '\n')
- buf[--j] = '#';
- buf[--j] = buf[i];
- }
- buf[0] = '#';
- *lenp += n;
- return 1;
- }
-}
-
-/* ------------------------------------------------------------------------- */
-/* Common file/command completion code for vi/emacs */
-
-
-static char *add_glob ARGS((const char *str, int slen));
-static void glob_table ARGS((const char *pat, XPtrV *wp, struct table *tp));
-static void glob_path ARGS((int flags, const char *pat, XPtrV *wp,
- const char *path));
-
-#if 0 /* not used... */
-int x_complete_word ARGS((const char *str, int slen, int is_command,
- int *multiple, char **ret));
-int
-x_complete_word(str, slen, is_command, nwordsp, ret)
- const char *str;
- int slen;
- int is_command;
- int *nwordsp;
- char **ret;
-{
- int nwords;
- int prefix_len;
- char **words;
-
- nwords = (is_command ? x_command_glob : x_file_glob)(XCF_FULLPATH,
- str, slen, &words);
- *nwordsp = nwords;
- if (nwords == 0) {
- *ret = (char *) 0;
- return -1;
- }
-
- prefix_len = x_longest_prefix(nwords, words);
- *ret = str_nsave(words[0], prefix_len, ATEMP);
- x_free_words(nwords, words);
- return prefix_len;
-}
-#endif /* 0 */
-
-void
-x_print_expansions(nwords, words, is_command)
- int nwords;
- char *const *words;
- int is_command;
-{
- int use_copy = 0;
- int prefix_len;
- XPtrV l;
-
- /* Check if all matches are in the same directory (in this
- * case, we want to omitt the directory name)
- */
- if (!is_command
- && (prefix_len = x_longest_prefix(nwords, words)) > 0)
- {
- int i;
-
- /* Special case for 1 match (prefix is whole word) */
- if (nwords == 1)
- prefix_len = x_basename(words[0], (char *) 0);
- /* Any (non-trailing) slashes in non-common word suffixes? */
- for (i = 0; i < nwords; i++)
- if (x_basename(words[i] + prefix_len, (char *) 0)
- > prefix_len)
- break;
- /* All in same directory? */
- if (i == nwords) {
- while (prefix_len > 0
- && !ISDIRSEP(words[0][prefix_len - 1]))
- prefix_len--;
- use_copy = 1;
- XPinit(l, nwords + 1);
- for (i = 0; i < nwords; i++)
- XPput(l, words[i] + prefix_len);
- XPput(l, (char *) 0);
- }
- }
-
- /*
- * Enumerate expansions
- */
- x_putc('\r');
- x_putc('\n');
- pr_menu(use_copy ? (char **) XPptrv(l) : words);
-
- if (use_copy)
- XPfree(l); /* not x_free_words() */
-}
-
-/*
- * Do file globbing:
- * - appends * to (copy of) str if no globbing chars found
- * - does expansion, checks for no match, etc.
- * - sets *wordsp to array of matching strings
- * - returns number of matching strings
- */
-static int
-x_file_glob(flags, str, slen, wordsp)
- int flags;
- const char *str;
- int slen;
- char ***wordsp;
-{
- char *toglob;
- char **words;
- int nwords;
- XPtrV w;
- struct source *s, *sold;
-
- if (slen < 0)
- return 0;
-
- toglob = add_glob(str, slen);
-
- /*
- * Convert "foo*" (toglob) to an array of strings (words)
- */
- sold = source;
- s = pushs(SWSTR, ATEMP);
- s->start = s->str = toglob;
- source = s;
- if (yylex(ONEWORD) != LWORD) {
- source = sold;
- internal_errorf(0, "fileglob: substitute error");
- return 0;
- }
- source = sold;
- XPinit(w, 32);
- expand(yylval.cp, &w, DOGLOB|DOTILDE|DOMARKDIRS);
- XPput(w, NULL);
- words = (char **) XPclose(w);
-
- for (nwords = 0; words[nwords]; nwords++)
- ;
- if (nwords == 1) {
- struct stat statb;
-
- /* Check if globbing failed (returned glob pattern),
- * but be careful (E.g. toglob == "ab*" when the file
- * "ab*" exists is not an error).
- * Also, check for empty result - happens if we tried
- * to glob something which evaluated to an empty
- * string (e.g., "$FOO" when there is no FOO, etc).
- */
- if ((strcmp(words[0], toglob) == 0
- && stat(words[0], &statb) < 0)
- || words[0][0] == '\0')
- {
- x_free_words(nwords, words);
- nwords = 0;
- }
- }
- afree(toglob, ATEMP);
-
- *wordsp = nwords ? words : (char **) 0;
-
- return nwords;
-}
-
-/* Data structure used in x_command_glob() */
-struct path_order_info {
- char *word;
- int base;
- int path_order;
-};
-
-/* Compare routine used in x_command_glob() */
-static int
-path_order_cmp(aa, bb)
- const void *aa;
- const void *bb;
-{
- const struct path_order_info *a = (const struct path_order_info *) aa;
- const struct path_order_info *b = (const struct path_order_info *) bb;
- int t;
-
- t = FILECMP(a->word + a->base, b->word + b->base);
- return t ? t : a->path_order - b->path_order;
-}
-
-static int
-x_command_glob(flags, str, slen, wordsp)
- int flags;
- const char *str;
- int slen;
- char ***wordsp;
-{
- char *toglob;
- char *pat;
- char *fpath;
- int nwords;
- XPtrV w;
- struct block *l;
-
- if (slen < 0)
- return 0;
-
- toglob = add_glob(str, slen);
-
- /* Convert "foo*" (toglob) to a pattern for future use */
- pat = evalstr(toglob, DOPAT|DOTILDE);
- afree(toglob, ATEMP);
-
- XPinit(w, 32);
-
- glob_table(pat, &w, &keywords);
- glob_table(pat, &w, &aliases);
- glob_table(pat, &w, &builtins);
- for (l = e->loc; l; l = l->next)
- glob_table(pat, &w, &l->funs);
-
- glob_path(flags, pat, &w, path);
- if ((fpath = str_val(global("FPATH"))) != null)
- glob_path(flags, pat, &w, fpath);
-
- nwords = XPsize(w);
-
- if (!nwords) {
- *wordsp = (char **) 0;
- XPfree(w);
- return 0;
- }
-
- /* Sort entries */
- if (flags & XCF_FULLPATH) {
- /* Sort by basename, then path order */
- struct path_order_info *info;
- struct path_order_info *last_info = 0;
- char **words = (char **) XPptrv(w);
- int path_order = 0;
- int i;
-
- info = (struct path_order_info *)
- alloc(sizeof(struct path_order_info) * nwords, ATEMP);
- for (i = 0; i < nwords; i++) {
- info[i].word = words[i];
- info[i].base = x_basename(words[i], (char *) 0);
- if (!last_info || info[i].base != last_info->base
- || FILENCMP(words[i],
- last_info->word, info[i].base) != 0)
- {
- last_info = &info[i];
- path_order++;
- }
- info[i].path_order = path_order;
- }
- qsort(info, nwords, sizeof(struct path_order_info),
- path_order_cmp);
- for (i = 0; i < nwords; i++)
- words[i] = info[i].word;
- afree((void *) info, ATEMP);
- } else {
- /* Sort and remove duplicate entries */
- char **words = (char **) XPptrv(w);
- int i, j;
-
- qsortp(XPptrv(w), (size_t) nwords, xstrcmp);
-
- for (i = j = 0; i < nwords - 1; i++) {
- if (strcmp(words[i], words[i + 1]))
- words[j++] = words[i];
- else
- afree(words[i], ATEMP);
- }
- words[j++] = words[i];
- nwords = j;
- w.cur = (void **) &words[j];
- }
-
- XPput(w, NULL);
- *wordsp = (char **) XPclose(w);
-
- return nwords;
-}
-
-#define IS_WORDC(c) !isspace(c)
-
-static int
-x_locate_word(buf, buflen, pos, startp, is_commandp)
- const char *buf;
- int buflen;
- int pos;
- int *startp;
- int *is_commandp;
-{
- int p;
- int start, end;
-
- /* Bad call? Probably should report error */
- if (pos < 0 || pos > buflen) {
- *startp = pos;
- *is_commandp = 0;
- return 0;
- }
-
- if (pos == buflen) {
- if (pos == 0) { /* empty buffer? */
- *startp = pos;
- *is_commandp = 1;
- return 0;
- }
- pos--;
- }
-
- start = pos;
- /* Keep going backwards to start of word (has effect of allowing
- * one blank after the end of a word)
- */
- for (; start > 0 && IS_WORDC(buf[start - 1]); start--)
- ;
- /* Go forwards to end of word */
- for (end = start; end < buflen && IS_WORDC(buf[end]); end++)
- ;
-
- if (is_commandp) {
- int iscmd;
-
- /* Figure out if this is a command */
- for (p = start - 1; p >= 0 && isspace(buf[p]); p--)
- ;
- iscmd = p < 0 || strchr(";|&()", buf[p]);
- if (iscmd) {
- /* If command has a /, path, etc. is not searched;
- * only current directory is searched, which is just
- * like file globbing.
- */
- for (p = start; p < end; p++)
- if (ISDIRSEP(buf[p]))
- break;
- iscmd = p == end;
- }
- *is_commandp = iscmd;
- }
-
- *startp = start;
-
- return end - start;
-}
-
-int
-x_cf_glob(flags, buf, buflen, pos, startp, endp, wordsp, is_commandp)
- int flags;
- const char *buf;
- int buflen;
- int pos;
- int *startp;
- int *endp;
- char ***wordsp;
- int *is_commandp;
-{
- int len;
- int nwords;
- char **words;
- int is_command;
-
- len = x_locate_word(buf, buflen, pos, startp, &is_command);
- if (!(flags & XCF_COMMAND))
- is_command = 0;
- /* Don't do command globing on zero length strings - it takes too
- * long and isn't very useful. File globs are more likely to be
- * useful, so allow these.
- */
- if (len == 0 && is_command)
- return 0;
-
- nwords = (is_command ? x_command_glob : x_file_glob)(flags,
- buf + *startp, len, &words);
- if (nwords == 0) {
- *wordsp = (char **) 0;
- return 0;
- }
-
- if (is_commandp)
- *is_commandp = is_command;
- *wordsp = words;
- *endp = *startp + len;
-
- return nwords;
-}
-
-/* Given a string, copy it and possibly add a '*' to the end. The
- * new string is returned.
- */
-static char *
-add_glob(str, slen)
- const char *str;
- int slen;
-{
- char *toglob;
- char *s;
- bool_t saw_slash = FALSE;
-
- if (slen < 0)
- return (char *) 0;
-
- toglob = str_nsave(str, slen + 1, ATEMP); /* + 1 for "*" */
- toglob[slen] = '\0';
-
- /*
- * If the pathname contains a wildcard (an unquoted '*',
- * '?', or '[') or parameter expansion ('$'), or a ~username
- * with no trailing slash, then it is globbed based on that
- * value (i.e., without the appended '*').
- */
- for (s = toglob; *s; s++) {
- if (*s == '\\' && s[1])
- s++;
- else if (*s == '*' || *s == '[' || *s == '?' || *s == '$'
- || (s[1] == '(' /*)*/ && strchr("*+?@!", *s)))
- break;
- else if (ISDIRSEP(*s))
- saw_slash = TRUE;
- }
- if (!*s && (*toglob != '~' || saw_slash)) {
- toglob[slen] = '*';
- toglob[slen + 1] = '\0';
- }
-
- return toglob;
-}
-
-/*
- * Find longest common prefix
- */
-int
-x_longest_prefix(nwords, words)
- int nwords;
- char *const *words;
-{
- int i, j;
- int prefix_len;
- char *p;
-
- if (nwords <= 0)
- return 0;
-
- prefix_len = strlen(words[0]);
- for (i = 1; i < nwords; i++)
- for (j = 0, p = words[i]; j < prefix_len; j++)
- if (FILECHCONV(p[j]) != FILECHCONV(words[0][j])) {
- prefix_len = j;
- break;
- }
- return prefix_len;
-}
-
-void
-x_free_words(nwords, words)
- int nwords;
- char **words;
-{
- int i;
-
- for (i = 0; i < nwords; i++)
- if (words[i])
- afree(words[i], ATEMP);
- afree(words, ATEMP);
-}
-
-/* Return the offset of the basename of string s (which ends at se - need not
- * be null terminated). Trailing slashes are ignored. If s is just a slash,
- * then the offset is 0 (actually, length - 1).
- * s Return
- * /etc 1
- * /etc/ 1
- * /etc// 1
- * /etc/fo 5
- * foo 0
- * /// 2
- * 0
- */
-int
-x_basename(s, se)
- const char *s;
- const char *se;
-{
- const char *p;
-
- if (se == (char *) 0)
- se = s + strlen(s);
- if (s == se)
- return 0;
-
- /* Skip trailing slashes */
- for (p = se - 1; p > s && ISDIRSEP(*p); p--)
- ;
- for (; p > s && !ISDIRSEP(*p); p--)
- ;
- if (ISDIRSEP(*p) && p + 1 < se)
- p++;
-
- return p - s;
-}
-
-/*
- * Apply pattern matching to a table: all table entries that match a pattern
- * are added to wp.
- */
-static void
-glob_table(pat, wp, tp)
- const char *pat;
- XPtrV *wp;
- struct table *tp;
-{
- struct tstate ts;
- struct tbl *te;
-
- for (twalk(&ts, tp); (te = tnext(&ts)); ) {
- if (gmatch(te->name, pat, FALSE))
- XPput(*wp, str_save(te->name, ATEMP));
- }
-}
-
-static void
-glob_path(flags, pat, wp, path)
- int flags;
- const char *pat;
- XPtrV *wp;
- const char *path;
-{
- const char *sp, *p;
- char *xp;
- int pathlen;
- int patlen;
- int oldsize, newsize, i, j;
- char **words;
- XString xs;
-
- patlen = strlen(pat) + 1;
- sp = path;
- Xinit(xs, xp, patlen + 128, ATEMP);
- while (sp) {
- xp = Xstring(xs, xp);
- if (!(p = strchr(sp, PATHSEP)))
- p = sp + strlen(sp);
- pathlen = p - sp;
- if (pathlen) {
- /* Copy sp into xp, stuffing any MAGIC characters
- * on the way
- */
- const char *s = sp;
-
- XcheckN(xs, xp, pathlen * 2);
- while (s < p) {
- if (ISMAGIC(*s))
- *xp++ = MAGIC;
- *xp++ = *s++;
- }
- *xp++ = DIRSEP;
- pathlen++;
- }
- sp = p;
- XcheckN(xs, xp, patlen);
- memcpy(xp, pat, patlen);
-
- oldsize = XPsize(*wp);
- glob_str(Xstring(xs, xp), wp, 0);
- newsize = XPsize(*wp);
-
- /* Check that each match is executable... */
- words = (char **) XPptrv(*wp);
- for (i = j = oldsize; i < newsize; i++) {
- if (search_access(words[i], X_OK, (int *) 0) >= 0) {
- words[j] = words[i];
- if (!(flags & XCF_FULLPATH))
- memmove(words[j], words[j] + pathlen,
- strlen(words[j] + pathlen) + 1);
- j++;
- } else
- afree(words[i], ATEMP);
- }
- wp->cur = (void **) &words[j];
-
- if (!*sp++)
- break;
- }
- Xfree(xs, xp);
-}
-
-#endif /* EDIT */
diff --git a/bin/pdksh/edit.h b/bin/pdksh/edit.h
deleted file mode 100644
index fd29701cc06..00000000000
--- a/bin/pdksh/edit.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/* $OpenBSD: edit.h,v 1.2 1996/08/19 20:08:48 downsj Exp $ */
-
-/* NAME:
- * edit.h - globals for edit modes
- *
- * DESCRIPTION:
- * This header defines various global edit objects.
- *
- * SEE ALSO:
- *
- *
- * RCSid:
- * $From: edit.h,v 1.2 1994/05/19 18:32:40 michael Exp michael $
- *
- */
-
-/* some useful #defines */
-#ifdef EXTERN
-# define I__(i) = i
-#else
-# define I__(i)
-# define EXTERN extern
-# define EXTERN_DEFINED
-#endif
-
-#define BEL 0x07
-
-/* tty driver characters we are interested in */
-typedef struct {
- int erase;
- int kill;
- int werase;
- int intr;
- int quit;
- int eof;
-} X_chars;
-
-EXTERN X_chars edchars;
-
-/* x_fc_glob() flags */
-#define XCF_COMMAND BIT(0) /* Do command completion */
-#define XCF_FILE BIT(1) /* Do file completion */
-#define XCF_FULLPATH BIT(2) /* command completion: store full path */
-#define XCF_COMMAND_FILE (XCF_COMMAND|XCF_FILE)
-
-/* edit.c */
-int x_getc ARGS((void));
-void x_flush ARGS((void));
-void x_putc ARGS((int c));
-void x_puts ARGS((const char *s));
-bool_t x_mode ARGS((bool_t onoff));
-int promptlen ARGS((const char *cp, const char **spp));
-int x_do_comment ARGS((char *buf, int bsize, int *lenp));
-void x_print_expansions ARGS((int nwords, char *const *words, int is_command));
-int x_cf_glob ARGS((int flags, const char *buf, int buflen, int pos, int *startp,
- int *endp, char ***wordsp, int *is_commandp));
-int x_longest_prefix ARGS((int nwords, char *const *words));
-int x_basename ARGS((const char *s, const char *se));
-void x_free_words ARGS((int nwords, char **words));
-/* emacs.c */
-int x_emacs ARGS((char *buf, size_t len));
-void x_init_emacs ARGS((void));
-void x_emacs_keys ARGS((X_chars *ec));
-/* vi.c */
-int x_vi ARGS((char *buf, size_t len));
-
-
-#ifdef DEBUG
-# define D__(x) x
-#else
-# define D__(x)
-#endif
-
-/* This lot goes at the END */
-/* be sure not to interfere with anyone else's idea about EXTERN */
-#ifdef EXTERN_DEFINED
-# undef EXTERN_DEFINED
-# undef EXTERN
-#endif
-#undef I__
-/*
- * Local Variables:
- * version-control:t
- * comment-column:40
- * End:
- */
diff --git a/bin/pdksh/emacs-gen.sh b/bin/pdksh/emacs-gen.sh
deleted file mode 100644
index 97449de8fa4..00000000000
--- a/bin/pdksh/emacs-gen.sh
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/bin/sh
-# $OpenBSD: emacs-gen.sh,v 1.1 1996/08/14 06:19:10 downsj Exp $
-
-case $# in
-1) file=$1;;
-*)
- echo "$0: Usage: $0 path-to-emacs.c" 1>&2
- exit 1
-esac;
-
-if [ ! -r "$file" ] ;then
- echo "$0: can't read $file" 1>&2
- exit 1
-fi
-
-cat << E_O_F || exit 1
-/*
- * NOTE: THIS FILE WAS GENERATED AUTOMATICALLY FROM $file
- *
- * DO NOT BOTHER EDITING THIS FILE
- */
-E_O_F
-
-# Pass 1: print out lines before @START-FUNC-TAB@
-# and generate defines and function declarations,
-sed -e '1,/@START-FUNC-TAB@/d' -e '/@END-FUNC-TAB@/,$d' < $file |
- awk 'BEGIN { nfunc = 0; }
- /^[ ]*#/ {
- print $0;
- next;
- }
- {
- fname = $2;
- c = substr(fname, length(fname), 1);
- if (c == ",")
- fname = substr(fname, 1, length(fname) - 1);
- if (fname != "0") {
- printf "#define XFUNC_%s %d\n", substr(fname, 3, length(fname) - 2), nfunc;
- printf "static int %s ARGS((int c));\n", fname;
- nfunc++;
- }
- }' || exit 1
-
-exit 0
diff --git a/bin/pdksh/emacs.c b/bin/pdksh/emacs.c
deleted file mode 100644
index db515363a1d..00000000000
--- a/bin/pdksh/emacs.c
+++ /dev/null
@@ -1,2182 +0,0 @@
-/* $OpenBSD: emacs.c,v 1.4 1997/06/19 13:58:39 kstailey Exp $ */
-
-/*
- * Emacs-like command line editing and history
- *
- * created by Ron Natalie at BRL
- * modified by Doug Kingston, Doug Gwyn, and Lou Salkind
- * adapted to PD ksh by Eric Gisin
- */
-
-#include "config.h"
-#ifdef EMACS
-
-#include "sh.h"
-#include "ksh_stat.h"
-#include "ksh_dir.h"
-#include <ctype.h>
-#include "edit.h"
-
-static Area aedit;
-#define AEDIT &aedit /* area for kill ring and macro defns */
-
-#undef CTRL /* _BSD brain damage */
-#define CTRL(x) ((x) == '?' ? 0x7F : (x) & 0x1F) /* ASCII */
-#define UNCTRL(x) ((x) == 0x7F ? '?' : (x) | 0x40) /* ASCII */
-
-
-/* values returned by keyboard functions */
-#define KSTD 0
-#define KEOL 1 /* ^M, ^J */
-#define KINTR 2 /* ^G, ^C */
-
-struct x_ftab {
- int (*xf_func) ARGS((int c));
- const char *xf_name;
- short xf_flags;
-};
-
-/* index into struct x_ftab x_ftab[] - small is good */
-typedef unsigned char Findex;
-
-struct x_defbindings {
- Findex xdb_func; /* XFUNC_* */
- char xdb_tab;
- unsigned char xdb_char;
-};
-
-#define XF_ARG 1 /* command takes number prefix */
-#define XF_NOBIND 2 /* not allowed to bind to function */
-#define XF_PREFIX 4 /* function sets prefix */
-
-/* Separator for completion */
-#define is_cfs(c) (c == ' ' || c == '\t' || c == '"' || c == '\'')
-#define is_mfs(c) (!(isalnum(c) || c == '_' || c == '$')) /* Separator for motion */
-
-#ifdef OS2
- /* Deal with 8 bit chars & an extra prefix for function key (these two
- * changes increase memory usage from 9,216 bytes to 24,416 bytes...)
- */
-# define CHARMASK 0xFF /* 8-bit ASCII character mask */
-# define X_TABSZ 256 /* size of keydef tables etc */
-# define X_NTABS 4 /* normal, meta1, meta2, meta3 */
-static int x_prefix3 = 0xE0;
-#else /* OS2 */
-# define CHARMASK 0x7F /* 7-bit ASCII character mask */
-# define X_TABSZ 128 /* size of keydef tables etc */
-# define X_NTABS 3 /* normal, meta1, meta2 */
-#endif /* OS2 */
-
-/* Arguments for do_complete()
- * 0 = enumerate M-= complete as much as possible and then list
- * 1 = complete M-Esc
- * 2 = list M-?
- */
-typedef enum { CT_LIST, /* list the possible completions */
- CT_COMPLETE, /* complete to longest prefix */
- CT_COMPLIST /* complete and then list (if non-exact) */
- } Comp_type;
-
-/* { from 4.9 edit.h */
-/*
- * The following are used for my horizontal scrolling stuff
- */
-static char *xbuf; /* beg input buffer */
-static char *xend; /* end input buffer */
-static char *xcp; /* current position */
-static char *xep; /* current end */
-static char *xbp; /* start of visible portion of input buffer */
-static char *xlp; /* last char visible on screen */
-static int x_adj_ok;
-/*
- * we use x_adj_done so that functions can tell
- * whether x_adjust() has been called while they are active.
- */
-static int x_adj_done;
-
-static int xx_cols;
-static int x_col;
-static int x_displen;
-static int x_arg; /* general purpose arg */
-static int x_arg_defaulted;/* x_arg not explicitly set; defaulted to 1 */
-
-static int xlp_valid;
-/* end from 4.9 edit.h } */
-
-static int x_prefix1 = CTRL('['), x_prefix2 = CTRL('X');
-static char **x_histp; /* history position */
-static int x_nextcmd; /* for newline-and-next */
-static char *xmp; /* mark pointer */
-static Findex x_last_command;
-static Findex (*x_tab)[X_TABSZ]; /* key definition */
-static char *(*x_atab)[X_TABSZ]; /* macro definitions */
-#define KILLSIZE 20
-static char *killstack[KILLSIZE];
-static int killsp, killtp;
-static int x_curprefix;
-static char *macroptr;
-static int prompt_skip;
-
-static int x_ins ARGS((char *cp));
-static void x_delete ARGS((int nc, int force_push));
-static int x_bword ARGS((void));
-static int x_fword ARGS((void));
-static void x_goto ARGS((char *cp));
-static void x_bs ARGS((int c));
-static int x_size_str ARGS((char *cp));
-static int x_size ARGS((int c));
-static void x_zots ARGS((char *str));
-static void x_zotc ARGS((int c));
-static void x_load_hist ARGS((char **hp));
-static int x_search ARGS((char *pat, int sameline, int offset));
-static int x_match ARGS((char *str, char *pat));
-static void x_redraw ARGS((int limit));
-static void x_push ARGS((int nchars));
-static char * x_mapin ARGS((const char *cp));
-static char * x_mapout ARGS((int c));
-static void x_print ARGS((int prefix, int key));
-static void x_adjust ARGS((void));
-static void x_e_ungetc ARGS((int c));
-static int x_e_getc ARGS((void));
-static void x_e_putc ARGS((int c));
-static void x_e_puts ARGS((const char *s));
-static int x_comment ARGS((int c));
-static int x_fold_case ARGS((int c));
-static char *x_lastcp ARGS((void));
-static void do_complete ARGS((int flags, Comp_type type));
-
-
-/* The lines between START-FUNC-TAB .. END-FUNC-TAB are run through a
- * script (emacs-gen.sh) that generates emacs.out which contains:
- * - function declarations for x_* functions
- * - defines of the form XFUNC_<name> where <name> is function
- * name, sans leading x_.
- * Note that the script treats #ifdef and { 0, 0, 0} specially - use with
- * caution.
- */
-#include "emacs.out"
-static const struct x_ftab x_ftab[] = {
-/* @START-FUNC-TAB@ */
- { x_abort, "abort", 0 },
- { x_beg_hist, "beginning-of-history", 0 },
- { x_comp_comm, "complete-command", 0 },
- { x_comp_file, "complete-file", 0 },
- { x_complete, "complete", 0 },
- { x_del_back, "delete-char-backward", XF_ARG },
- { x_del_bword, "delete-word-backward", XF_ARG },
- { x_del_char, "delete-char-forward", XF_ARG },
- { x_del_fword, "delete-word-forward", XF_ARG },
- { x_del_line, "kill-line", 0 },
- { x_draw_line, "redraw", 0 },
- { x_end_hist, "end-of-history", 0 },
- { x_end_of_text, "eot", 0 },
- { x_enumerate, "list", 0 },
- { x_eot_del, "eot-or-delete", XF_ARG },
- { x_error, "error", 0 },
- { x_goto_hist, "goto-history", XF_ARG },
- { x_ins_string, "macro-string", XF_NOBIND },
- { x_insert, "auto-insert", XF_ARG },
- { x_kill, "kill-to-eol", XF_ARG },
- { x_kill_region, "kill-region", 0 },
- { x_list_comm, "list-command", 0 },
- { x_list_file, "list-file", 0 },
- { x_literal, "quote", 0 },
- { x_meta1, "prefix-1", XF_PREFIX },
- { x_meta2, "prefix-2", XF_PREFIX },
- { x_meta_yank, "yank-pop", 0 },
- { x_mv_back, "backward-char", XF_ARG },
- { x_mv_begin, "beginning-of-line", 0 },
- { x_mv_bword, "backward-word", XF_ARG },
- { x_mv_end, "end-of-line", 0 },
- { x_mv_forw, "forward-char", XF_ARG },
- { x_mv_fword, "forward-word", XF_ARG },
- { x_newline, "newline", 0 },
- { x_next_com, "down-history", XF_ARG },
- { x_nl_next_com, "newline-and-next", 0 },
- { x_noop, "no-op", 0 },
- { x_prev_com, "up-history", XF_ARG },
- { x_prev_histword, "prev-hist-word", XF_ARG },
- { x_search_char_forw, "search-character-forward", XF_ARG },
- { x_search_char_back, "search-character-backward", XF_ARG },
- { x_search_hist, "search-history", 0 },
- { x_set_mark, "set-mark-command", 0 },
- { x_stuff, "stuff", 0 },
- { x_stuffreset, "stuff-reset", 0 },
- { x_transpose, "transpose-chars", 0 },
- { x_version, "version", 0 },
- { x_xchg_point_mark, "exchange-point-and-mark", 0 },
- { x_yank, "yank", 0 },
- { x_comp_list, "complete-list", 0 },
- { x_expand, "expand-file", 0 },
- { x_fold_capitialize, "capitalize-word", XF_ARG },
- { x_fold_lower, "downcase-word", XF_ARG },
- { x_fold_upper, "upcase-word", XF_ARG },
- { x_set_arg, "set-arg", XF_NOBIND },
- { x_comment, "comment", 0 },
-#ifdef SILLY
- { x_game_of_life, "play-game-of-life", 0 },
-#else
- { 0, 0, 0 },
-#endif
-#ifdef DEBUG
- { x_debug_info, "debug-info", 0 },
-#else
- { 0, 0, 0 },
-#endif
-#ifdef OS2
- { x_meta3, "prefix-3", XF_PREFIX },
-#else
- { 0, 0, 0 },
-#endif
-/* @END-FUNC-TAB@ */
- };
-
-static struct x_defbindings const x_defbindings[] = {
- { XFUNC_del_back, 0, CTRL('?') },
- { XFUNC_del_bword, 1, CTRL('?') },
- { XFUNC_eot_del, 0, CTRL('D') },
- { XFUNC_del_back, 0, CTRL('H') },
- { XFUNC_del_bword, 1, CTRL('H') },
- { XFUNC_del_bword, 1, 'h' },
- { XFUNC_mv_bword, 1, 'b' },
- { XFUNC_mv_fword, 1, 'f' },
- { XFUNC_del_fword, 1, 'd' },
- { XFUNC_mv_back, 0, CTRL('B') },
- { XFUNC_mv_forw, 0, CTRL('F') },
- { XFUNC_search_char_forw, 0, CTRL(']') },
- { XFUNC_search_char_back, 1, CTRL(']') },
- { XFUNC_newline, 0, CTRL('M') },
- { XFUNC_newline, 0, CTRL('J') },
- { XFUNC_end_of_text, 0, CTRL('_') },
- { XFUNC_abort, 0, CTRL('G') },
- { XFUNC_prev_com, 0, CTRL('P') },
- { XFUNC_next_com, 0, CTRL('N') },
- { XFUNC_nl_next_com, 0, CTRL('O') },
- { XFUNC_search_hist, 0, CTRL('R') },
- { XFUNC_beg_hist, 1, '<' },
- { XFUNC_end_hist, 1, '>' },
- { XFUNC_goto_hist, 1, 'g' },
- { XFUNC_mv_end, 0, CTRL('E') },
- { XFUNC_mv_begin, 0, CTRL('A') },
- { XFUNC_draw_line, 0, CTRL('L') },
- { XFUNC_meta1, 0, CTRL('[') },
- { XFUNC_meta2, 0, CTRL('X') },
- { XFUNC_kill, 0, CTRL('K') },
- { XFUNC_yank, 0, CTRL('Y') },
- { XFUNC_meta_yank, 1, 'y' },
- { XFUNC_literal, 0, CTRL('^') },
- { XFUNC_comment, 1, '#' },
-#if defined(BRL) && defined(TIOCSTI)
- { XFUNC_stuff, 0, CTRL('T') },
-#else
- { XFUNC_transpose, 0, CTRL('T') },
-#endif
- { XFUNC_complete, 1, CTRL('[') },
- { XFUNC_comp_list, 1, '=' },
- { XFUNC_enumerate, 1, '?' },
- { XFUNC_expand, 1, '*' },
- { XFUNC_comp_file, 1, CTRL('X') },
- { XFUNC_comp_comm, 2, CTRL('[') },
- { XFUNC_list_comm, 2, '?' },
- { XFUNC_list_file, 2, CTRL('Y') },
- { XFUNC_set_mark, 1, ' ' },
- { XFUNC_kill_region, 0, CTRL('W') },
- { XFUNC_xchg_point_mark, 2, CTRL('X') },
- { XFUNC_version, 0, CTRL('V') },
-#ifdef DEBUG
- { XFUNC_debug_info, 1, CTRL('H') },
-#endif
- { XFUNC_prev_histword, 1, '.' },
- { XFUNC_prev_histword, 1, '_' },
- { XFUNC_set_arg, 1, '0' },
- { XFUNC_set_arg, 1, '1' },
- { XFUNC_set_arg, 1, '2' },
- { XFUNC_set_arg, 1, '3' },
- { XFUNC_set_arg, 1, '4' },
- { XFUNC_set_arg, 1, '5' },
- { XFUNC_set_arg, 1, '6' },
- { XFUNC_set_arg, 1, '7' },
- { XFUNC_set_arg, 1, '8' },
- { XFUNC_set_arg, 1, '9' },
- { XFUNC_fold_upper, 1, 'U' },
- { XFUNC_fold_upper, 1, 'u' },
- { XFUNC_fold_lower, 1, 'L' },
- { XFUNC_fold_lower, 1, 'l' },
- { XFUNC_fold_capitialize, 1, 'C' },
- { XFUNC_fold_capitialize, 1, 'c' },
-#ifdef OS2
- { XFUNC_meta3, 0, 0xE0 },
- { XFUNC_mv_back, 3, 'K' },
- { XFUNC_mv_forw, 3, 'M' },
- { XFUNC_next_com, 3, 'P' },
- { XFUNC_prev_com, 3, 'H' },
-#else /* OS2 */
- /* These for ansi arrow keys: arguablely shouldn't be here by
- * default, but its simpler/faster/smaller than using termcap
- * entries.
- */
- { XFUNC_meta2, 1, '[' },
- { XFUNC_prev_com, 2, 'A' },
- { XFUNC_next_com, 2, 'B' },
- { XFUNC_mv_forw, 2, 'C' },
- { XFUNC_mv_back, 2, 'D' },
-#endif /* OS2 */
-};
-
-int
-x_emacs(buf, len)
- char *buf;
- size_t len;
-{
- int c;
- const char *p;
- int i;
- Findex f;
-
- xbp = xbuf = buf; xend = buf + len;
- xlp = xcp = xep = buf;
- *xcp = 0;
- xlp_valid = TRUE;
- xmp = NULL;
- x_curprefix = 0;
- macroptr = (char *) 0;
- x_histp = histptr + 1;
- x_last_command = XFUNC_error;
-
- xx_cols = x_cols;
- x_col = promptlen(prompt, &p);
- prompt_skip = p - prompt;
- x_adj_ok = 1;
- x_displen = xx_cols - 2 - x_col;
- x_adj_done = 0;
-
- pprompt(prompt, 0);
-
- if (x_nextcmd >= 0) {
- int off = source->line - x_nextcmd;
- if (histptr - history >= off)
- x_load_hist(histptr - off);
- x_nextcmd = -1;
- }
-
- while (1) {
- x_flush();
- if ((c = x_e_getc()) < 0)
- return 0;
-
- f = x_curprefix == -1 ? XFUNC_insert
- : x_tab[x_curprefix][c&CHARMASK];
-
- if (!(x_ftab[f].xf_flags & XF_PREFIX)
- && x_last_command != XFUNC_set_arg)
- {
- x_arg = 1;
- x_arg_defaulted = 1;
- }
- i = c | (x_curprefix << 8);
- x_curprefix = 0;
- switch (i = (*x_ftab[f].xf_func)(i)) {
- case KSTD:
- if (!(x_ftab[f].xf_flags & XF_PREFIX))
- x_last_command = f;
- break;
- case KEOL:
- i = xep - xbuf;
- return i;
- case KINTR: /* special case for interrupt */
- trapsig(SIGINT);
- x_mode(FALSE);
- unwind(LSHELL);
- }
- }
-}
-
-static int
-x_insert(c)
- int c;
-{
- char str[2];
-
- /*
- * Should allow tab and control chars.
- */
- if (c == 0) {
- x_e_putc(BEL);
- return KSTD;
- }
- str[0] = c;
- str[1] = '\0';
- while (x_arg--)
- x_ins(str);
- return KSTD;
-}
-
-static int
-x_ins_string(c)
- int c;
-{
- if (macroptr) {
- x_e_putc(BEL);
- return KSTD;
- }
- macroptr = x_atab[c>>8][c & CHARMASK];
- if (macroptr && !*macroptr) {
- /* XXX bell? */
- macroptr = (char *) 0;
- }
- return KSTD;
-}
-
-static int
-x_do_ins(cp, len)
- const char *cp;
- int len;
-{
- if (xep+len >= xend) {
- x_e_putc(BEL);
- return -1;
- }
-
- memmove(xcp+len, xcp, xep - xcp + 1);
- memmove(xcp, cp, len);
- xcp += len;
- xep += len;
- return 0;
-}
-
-static int
-x_ins(s)
- char *s;
-{
- char *cp = xcp;
- register int adj = x_adj_done;
-
- if (x_do_ins(s, strlen(s)) < 0)
- return -1;
- /*
- * x_zots() may result in a call to x_adjust()
- * we want xcp to reflect the new position.
- */
- xlp_valid = FALSE;
- x_lastcp();
- x_adj_ok = (xcp >= xlp);
- x_zots(cp);
- if (adj == x_adj_done) /* has x_adjust() been called? */
- {
- /* no */
- for (cp = xlp; cp > xcp; )
- x_bs(*--cp);
- }
-
- x_adj_ok = 1;
- return 0;
-}
-
-static int
-x_del_back(c)
- int c;
-{
- int col = xcp - xbuf;
-
- if (col == 0) {
- x_e_putc(BEL);
- return KSTD;
- }
- if (x_arg > col)
- x_arg = col;
- x_goto(xcp - x_arg);
- x_delete(x_arg, FALSE);
- return KSTD;
-}
-
-static int
-x_del_char(c)
- int c;
-{
- int nleft = xep - xcp;
-
- if (!nleft) {
- x_e_putc(BEL);
- return KSTD;
- }
- if (x_arg > nleft)
- x_arg = nleft;
- x_delete(x_arg, FALSE);
- return KSTD;
-}
-
-/* Delete nc chars to the right of the cursor (including cursor position) */
-static void
-x_delete(nc, force_push)
- int nc;
- int force_push;
-{
- int i,j;
- char *cp;
-
- if (nc == 0)
- return;
- if (xmp != NULL && xmp > xcp) {
- if (xcp + nc > xmp)
- xmp = xcp;
- else
- xmp -= nc;
- }
-
- /*
- * This lets us yank a word we have deleted.
- */
- if (nc > 1 || force_push)
- x_push(nc);
-
- xep -= nc;
- cp = xcp;
- j = 0;
- i = nc;
- while (i--) {
- j += x_size(*cp++);
- }
- memmove(xcp, xcp+nc, xep - xcp + 1); /* Copies the null */
- x_adj_ok = 0; /* don't redraw */
- x_zots(xcp);
- /*
- * if we are already filling the line,
- * there is no need to ' ','\b'.
- * But if we must, make sure we do the minimum.
- */
- if ((i = xx_cols - 2 - x_col) > 0)
- {
- j = (j < i) ? j : i;
- i = j;
- while (i--)
- x_e_putc(' ');
- i = j;
- while (i--)
- x_e_putc('\b');
- }
- /*x_goto(xcp);*/
- x_adj_ok = 1;
- xlp_valid = FALSE;
- for (cp = x_lastcp(); cp > xcp; )
- x_bs(*--cp);
-
- return;
-}
-
-static int
-x_del_bword(c)
- int c;
-{
- x_delete(x_bword(), FALSE);
- return KSTD;
-}
-
-static int
-x_mv_bword(c)
- int c;
-{
- (void)x_bword();
- return KSTD;
-}
-
-static int
-x_mv_fword(c)
- int c;
-{
- x_goto(xcp + x_fword());
- return KSTD;
-}
-
-static int
-x_del_fword(c)
- int c;
-{
- x_delete(x_fword(), FALSE);
- return KSTD;
-}
-
-static int
-x_bword()
-{
- int nc = 0;
- register char *cp = xcp;
-
- if (cp == xbuf) {
- x_e_putc(BEL);
- return 0;
- }
- while (x_arg--)
- {
- while (cp != xbuf && is_mfs(cp[-1]))
- {
- cp--;
- nc++;
- }
- while (cp != xbuf && !is_mfs(cp[-1]))
- {
- cp--;
- nc++;
- }
- }
- x_goto(cp);
- return nc;
-}
-
-static int
-x_fword()
-{
- int nc = 0;
- register char *cp = xcp;
-
- if (cp == xep) {
- x_e_putc(BEL);
- return 0;
- }
- while (x_arg--)
- {
- while (cp != xep && is_mfs(*cp))
- {
- cp++;
- nc++;
- }
- while (cp != xep && !is_mfs(*cp))
- {
- cp++;
- nc++;
- }
- }
- return nc;
-}
-
-static void
-x_goto(cp)
- register char *cp;
-{
- if (cp < xbp || cp >= (xbp + x_displen))
- {
- /* we are heading off screen */
- xcp = cp;
- x_adjust();
- }
- else
- {
- if (cp < xcp) /* move back */
- {
- while (cp < xcp)
- x_bs(*--xcp);
- }
- else
- {
- if (cp > xcp) /* move forward */
- {
- while (cp > xcp)
- x_zotc(*xcp++);
- }
- }
- }
-}
-
-static void
-x_bs(c)
- int c;
-{
- register i;
- i = x_size(c);
- while (i--)
- x_e_putc('\b');
-}
-
-static int
-x_size_str(cp)
- register char *cp;
-{
- register size = 0;
- while (*cp)
- size += x_size(*cp++);
- return size;
-}
-
-static int
-x_size(c)
- int c;
-{
- if (c=='\t')
- return 4; /* Kludge, tabs are always four spaces. */
- if (c < ' ' || c == 0x7F) /* ASCII control char */
- return 2;
- return 1;
-}
-
-static void
-x_zots(str)
- register char *str;
-{
- register int adj = x_adj_done;
-
- x_lastcp();
- while (*str && str < xlp && adj == x_adj_done)
- x_zotc(*str++);
-}
-
-static void
-x_zotc(c)
- int c;
-{
- if (c == '\t') {
- /* Kludge, tabs are always four spaces. */
- x_e_puts(" ");
- } else if (c < ' ' || c == 0x7F) { /* ASCII */
- x_e_putc('^');
- x_e_putc(UNCTRL(c));
- } else
- x_e_putc(c);
-}
-
-static int
-x_mv_back(c)
- int c;
-{
- int col = xcp - xbuf;
-
- if (col == 0) {
- x_e_putc(BEL);
- return KSTD;
- }
- if (x_arg > col)
- x_arg = col;
- x_goto(xcp - x_arg);
- return KSTD;
-}
-
-static int
-x_mv_forw(c)
- int c;
-{
- int nleft = xep - xcp;
-
- if (!nleft) {
- x_e_putc(BEL);
- return KSTD;
- }
- if (x_arg > nleft)
- x_arg = nleft;
- x_goto(xcp + x_arg);
- return KSTD;
-}
-
-static int
-x_search_char_forw(c)
- int c;
-{
- char *cp = xcp;
-
- *xep = '\0';
- c = x_e_getc();
- while (x_arg--) {
- if (c < 0
- || ((cp = (cp == xep) ? NULL : strchr(cp + 1, c)) == NULL
- && (cp = strchr(xbuf, c)) == NULL))
- {
- x_e_putc(BEL);
- return KSTD;
- }
- }
- x_goto(cp);
- return KSTD;
-}
-
-static int
-x_search_char_back(c)
- int c;
-{
- char *cp = xcp, *p;
-
- c = x_e_getc();
- for (; x_arg--; cp = p)
- for (p = cp; ; ) {
- if (p-- == xbuf)
- p = xep;
- if (c < 0 || p == cp) {
- x_e_putc(BEL);
- return KSTD;
- }
- if (*p == c)
- break;
- }
- x_goto(cp);
- return KSTD;
-}
-
-static int
-x_newline(c)
- int c;
-{
- x_e_putc('\r');
- x_e_putc('\n');
- x_flush();
- *xep++ = '\n';
- return KEOL;
-}
-
-static int
-x_end_of_text(c)
- int c;
-{
- return KEOL;
-}
-
-static int x_beg_hist(c) int c; { x_load_hist(history); return KSTD;}
-
-static int x_end_hist(c) int c; { x_load_hist(histptr); return KSTD;}
-
-static int x_prev_com(c) int c; { x_load_hist(x_histp - x_arg); return KSTD;}
-
-static int x_next_com(c) int c; { x_load_hist(x_histp + x_arg); return KSTD;}
-
-/* Goto a particular history number obtained from argument.
- * If no argument is given history 1 is probably not what you
- * want so we'll simply go to the oldest one.
- */
-static int
-x_goto_hist(c)
- int c;
-{
- if (x_arg_defaulted)
- x_load_hist(history);
- else
- x_load_hist(histptr + x_arg - source->line);
- return KSTD;
-}
-
-static void
-x_load_hist(hp)
- register char **hp;
-{
- int oldsize;
-
- if (hp < history || hp > histptr) {
- x_e_putc(BEL);
- return;
- }
- x_histp = hp;
- oldsize = x_size_str(xbuf);
- (void)strcpy(xbuf, *hp);
- xbp = xbuf;
- xep = xcp = xbuf + strlen(*hp);
- xlp_valid = FALSE;
- if (xep > x_lastcp())
- x_goto(xep);
- else
- x_redraw(oldsize);
-}
-
-static int
-x_nl_next_com(c)
- int c;
-{
- x_nextcmd = source->line - (histptr - x_histp) + 1;
- return (x_newline(c));
-}
-
-static int
-x_eot_del(c)
- int c;
-{
- if (xep == xbuf && x_arg_defaulted)
- return (x_end_of_text(c));
- else
- return (x_del_char(c));
-}
-
-/* reverse incremental history search */
-static int
-x_search_hist(c)
- int c;
-{
- int offset = -1; /* offset of match in xbuf, else -1 */
- char pat [256+1]; /* pattern buffer */
- register char *p = pat;
- Findex f;
-
- *p = '\0';
- while (1) {
- if (offset < 0) {
- x_e_puts("\nI-search: ");
- x_e_puts(pat);
- }
- x_flush();
- if ((c = x_e_getc()) < 0)
- return KSTD;
- f = x_tab[0][c&CHARMASK];
- if (c == CTRL('['))
- break;
- else if (f == XFUNC_search_hist)
- offset = x_search(pat, 0, offset);
- else if (f == XFUNC_del_back) {
- if (p == pat) {
- offset = -1;
- break;
- }
- if (p > pat)
- *--p = '\0';
- if (p == pat)
- offset = -1;
- else
- offset = x_search(pat, 1, offset);
- continue;
- } else if (f == XFUNC_insert) {
- /* add char to pattern */
- /* overflow check... */
- if (p >= &pat[sizeof(pat) - 1]) {
- x_e_putc(BEL);
- continue;
- }
- *p++ = c, *p = '\0';
- if (offset >= 0) {
- /* already have partial match */
- offset = x_match(xbuf, pat);
- if (offset >= 0) {
- x_goto(xbuf + offset + (p - pat) - (*pat == '^'));
- continue;
- }
- }
- offset = x_search(pat, 0, offset);
- } else { /* other command */
- x_e_ungetc(c);
- break;
- }
- }
- if (offset < 0)
- x_redraw(-1);
- return KSTD;
-}
-
-/* search backward from current line */
-static int
-x_search(pat, sameline, offset)
- char *pat;
- int sameline;
- int offset;
-{
- register char **hp;
- int i;
-
- for (hp = x_histp - (sameline ? 0 : 1) ; hp >= history; --hp) {
- i = x_match(*hp, pat);
- if (i >= 0) {
- if (offset < 0)
- x_e_putc('\n');
- x_load_hist(hp);
- x_goto(xbuf + i + strlen(pat) - (*pat == '^'));
- return i;
- }
- }
- x_e_putc(BEL);
- x_histp = histptr;
- return -1;
-}
-
-/* return position of first match of pattern in string, else -1 */
-static int
-x_match(str, pat)
- char *str, *pat;
-{
- if (*pat == '^') {
- return (strncmp(str, pat+1, strlen(pat+1)) == 0) ? 0 : -1;
- } else {
- char *q = strstr(str, pat);
- return (q == NULL) ? -1 : q - str;
- }
-}
-
-static int
-x_del_line(c)
- int c;
-{
- int i, j;
-
- *xep = 0;
- i = xep- xbuf;
- j = x_size_str(xbuf);
- xcp = xbuf;
- x_push(i);
- xlp = xbp = xep = xbuf;
- xlp_valid = TRUE;
- *xcp = 0;
- xmp = NULL;
- x_redraw(j);
- return KSTD;
-}
-
-static int
-x_mv_end(c)
- int c;
-{
- x_goto(xep);
- return KSTD;
-}
-
-static int
-x_mv_begin(c)
- int c;
-{
- x_goto(xbuf);
- return KSTD;
-}
-
-static int
-x_draw_line(c)
- int c;
-{
- x_redraw(-1);
- return KSTD;
-
-}
-
-/* Redraw (part of) the line. If limit is < 0, the everything is redrawn
- * on a NEW line, otherwise limit is the screen column up to which needs
- * redrawing.
- */
-static void
-x_redraw(limit)
- int limit;
-{
- int i, j;
- char *cp;
-
- x_adj_ok = 0;
- if (limit == -1)
- x_e_putc('\n');
- else
- x_e_putc('\r');
- x_flush();
- if (xbp == xbuf)
- {
- pprompt(prompt + prompt_skip, 0);
- x_col = promptlen(prompt, (const char **) 0);
- }
- x_displen = xx_cols - 2 - x_col;
- xlp_valid = FALSE;
- cp = x_lastcp();
- x_zots(xbp);
- if (xbp != xbuf || xep > xlp)
- limit = xx_cols;
- if (limit >= 0)
- {
- if (xep > xlp)
- i = 0; /* we fill the line */
- else
- i = limit - (xlp - xbp);
-
- for (j = 0; j < i && x_col < (xx_cols - 2); j++)
- x_e_putc(' ');
- i = ' ';
- if (xep > xlp) /* more off screen */
- {
- if (xbp > xbuf)
- i = '*';
- else
- i = '>';
- }
- else
- if (xbp > xbuf)
- i = '<';
- x_e_putc(i);
- j++;
- while (j--)
- x_e_putc('\b');
- }
- for (cp = xlp; cp > xcp; )
- x_bs(*--cp);
- x_adj_ok = 1;
- D__(x_flush();)
- return;
-}
-
-static int
-x_transpose(c)
- int c;
-{
- char tmp;
-
- /* What transpose is meant to do seems to be up for debate. This
- * is a general summary of the options; the text is abcd with the
- * upper case character or underscore indicating the cursor positiion:
- * Who Before After Before After
- * at&t ksh in emacs mode: abCd abdC abcd_ (bell)
- * at&t ksh in gmacs mode: abCd baCd abcd_ abdc_
- * gnu emacs: abCd acbD abcd_ abdc_
- * Pdksh currently goes with GNU behavior since I believe this is the
- * most common version of emacs, unless in gmacs mode, in which case
- * it does the at&t ksh gmacs mdoe.
- * This should really be broken up into 3 functions so users can bind
- * to the one they want.
- */
- if (xcp == xbuf) {
- x_e_putc(BEL);
- return KSTD;
- } else if (xcp == xep || Flag(FGMACS)) {
- if (xcp - xbuf == 1) {
- x_e_putc(BEL);
- return KSTD;
- }
- /* Gosling/Unipress emacs style: Swap two characters before the
- * cursor, do not change cursor position
- */
- x_bs(xcp[-1]);
- x_bs(xcp[-2]);
- x_zotc(xcp[-1]);
- x_zotc(xcp[-2]);
- tmp = xcp[-1];
- xcp[-1] = xcp[-2];
- xcp[-2] = tmp;
- } else {
- /* GNU emacs style: Swap the characters before and under the
- * cursor, move cursor position along one.
- */
- x_bs(xcp[-1]);
- x_zotc(xcp[0]);
- x_zotc(xcp[-1]);
- tmp = xcp[-1];
- xcp[-1] = xcp[0];
- xcp[0] = tmp;
- x_bs(xcp[0]);
- x_goto(xcp + 1);
- }
- return KSTD;
-}
-
-static int
-x_literal(c)
- int c;
-{
- x_curprefix = -1;
- return KSTD;
-}
-
-static int
-x_meta1(c)
- int c;
-{
- x_curprefix = 1;
- return KSTD;
-}
-
-static int
-x_meta2(c)
- int c;
-{
- x_curprefix = 2;
- return KSTD;
-}
-
-#ifdef OS2
-static int
-x_meta3(c)
- int c;
-{
- x_curprefix = 3;
- return KSTD;
-}
-#endif /* OS2 */
-
-static int
-x_kill(c)
- int c;
-{
- int col = xcp - xbuf;
- int lastcol = xep - xbuf;
- int ndel;
-
- if (x_arg_defaulted)
- x_arg = lastcol;
- else if (x_arg > lastcol)
- x_arg = lastcol;
- ndel = x_arg - col;
- if (ndel < 0) {
- x_goto(xbuf + x_arg);
- ndel = -ndel;
- }
- x_delete(ndel, TRUE);
- return KSTD;
-}
-
-static void
-x_push(nchars)
- int nchars;
-{
- char *cp = str_nsave(xcp, nchars, AEDIT);
- if (killstack[killsp])
- afree((void *)killstack[killsp], AEDIT);
- killstack[killsp] = cp;
- killsp = (killsp + 1) % KILLSIZE;
-}
-
-static int
-x_yank(c)
- int c;
-{
- if (killsp == 0)
- killtp = KILLSIZE;
- else
- killtp = killsp;
- killtp --;
- if (killstack[killtp] == 0) {
- x_e_puts("\nnothing to yank");
- x_redraw(-1);
- return KSTD;
- }
- xmp = xcp;
- x_ins(killstack[killtp]);
- return KSTD;
-}
-
-static int
-x_meta_yank(c)
- int c;
-{
- int len;
- if (x_last_command != XFUNC_yank && x_last_command != XFUNC_meta_yank) {
- x_e_puts("\nyank something first");
- x_redraw(-1);
- return KSTD;
- }
- len = strlen(killstack[killtp]);
- x_goto(xcp - len);
- x_delete(len, FALSE);
- do {
- if (killtp == 0)
- killtp = KILLSIZE - 1;
- else
- killtp--;
- } while (killstack[killtp] == 0);
- x_ins(killstack[killtp]);
- return KSTD;
-}
-
-static int
-x_abort(c)
- int c;
-{
- /* x_zotc(c); */
- xlp = xep = xcp = xbp = xbuf;
- xlp_valid = TRUE;
- *xcp = 0;
- return KINTR;
-}
-
-static int
-x_error(c)
- int c;
-{
- x_e_putc(BEL);
- return KSTD;
-}
-
-static int
-x_stuffreset(c)
- int c;
-{
-#ifdef TIOCSTI
- (void)x_stuff(c);
- return KINTR;
-#else
- x_zotc(c);
- xlp = xcp = xep = xbp = xbuf;
- xlp_valid = TRUE;
- *xcp = 0;
- x_redraw(-1);
- return KSTD;
-#endif
-}
-
-static int
-x_stuff(c)
- int c;
-{
-#if 0 || defined TIOCSTI
- char ch = c;
- bool_t savmode = x_mode(FALSE);
-
- (void)ioctl(TTY, TIOCSTI, &ch);
- (void)x_mode(savmode);
- x_redraw(-1);
-#endif
- return KSTD;
-}
-
-static char *
-x_mapin(cp)
- const char *cp;
-{
- char *new, *op;
-
- op = new = str_save(cp, ATEMP);
- while (*cp) {
- /* XXX -- should handle \^ escape? */
- if (*cp == '^') {
- cp++;
-#ifdef OS2
- if (*cp == '0') /* To define function keys */
- *op++ = 0xE0;
- else
-#endif /* OS2 */
- if (*cp >= '?') /* includes '?'; ASCII */
- *op++ = CTRL(*cp);
- else {
- *op++ = '^';
- cp--;
- }
- } else
- *op++ = *cp;
- cp++;
- }
- *op = '\0';
-
- return new;
-}
-
-static char *
-x_mapout(c)
- int c;
-{
- static char buf[8];
- register char *p = buf;
-
- if (c < ' ' || c == 0x7F) { /* ASCII */
- *p++ = '^';
- *p++ = (c == 0x7F) ? '?' : (c | 0x40);
-#ifdef OS2
- } else if (c == 0xE0) {
- *p++ = '^';
- *p++ = '0';
-#endif /* OS2 */
- } else
- *p++ = c;
- *p = 0;
- return buf;
-}
-
-static void
-x_print(prefix, key)
- int prefix, key;
-{
- if (prefix == 1)
- shprintf("%s", x_mapout(x_prefix1));
- if (prefix == 2)
- shprintf("%s", x_mapout(x_prefix2));
-#ifdef OS2
- if (prefix == 3)
- shprintf("%s", x_mapout(x_prefix3));
-#endif /* OS2 */
- shprintf("%s = ", x_mapout(key));
- if (x_tab[prefix][key] != XFUNC_ins_string)
- shprintf("%s\n", x_ftab[x_tab[prefix][key]].xf_name);
- else
- shprintf("'%s'\n", x_atab[prefix][key]);
-}
-
-int
-x_bind(a1, a2, macro, list)
- const char *a1, *a2;
- int macro; /* bind -m */
- int list; /* bind -l */
-{
- Findex f;
- int prefix, key;
- char *sp = NULL;
- char *m1, *m2;
-
- if (x_tab == NULL) {
- bi_errorf("cannot bind, not a tty");
- return 1;
- }
-
- /* List function names */
- if (list) {
- for (f = 0; f < NELEM(x_ftab); f++)
- if (x_ftab[f].xf_name
- && !(x_ftab[f].xf_flags & XF_NOBIND))
- shprintf("%s\n", x_ftab[f].xf_name);
- return 0;
- }
-
- if (a1 == NULL) {
- for (prefix = 0; prefix < X_NTABS; prefix++)
- for (key = 0; key < X_TABSZ; key++) {
- f = x_tab[prefix][key];
- if (f == XFUNC_insert || f == XFUNC_error
- || (macro && f != XFUNC_ins_string))
- continue;
- x_print(prefix, key);
- }
- return 0;
- }
-
- m1 = x_mapin(a1);
- prefix = key = 0;
- for (;; m1++) {
- key = *m1 & CHARMASK;
- if (x_tab[prefix][key] == XFUNC_meta1)
- prefix = 1;
- else if (x_tab[prefix][key] == XFUNC_meta2)
- prefix = 2;
-#ifdef OS2
- else if (x_tab[prefix][key] == XFUNC_meta3)
- prefix = 3;
-#endif /* OS2 */
- else
- break;
- }
-
- if (a2 == NULL) {
- x_print(prefix, key);
- return 0;
- }
-
- if (*a2 == 0)
- f = XFUNC_insert;
- else if (!macro) {
- for (f = 0; f < NELEM(x_ftab); f++)
- if (x_ftab[f].xf_name
- && strcmp(x_ftab[f].xf_name, a2) == 0)
- break;
- if (f == NELEM(x_ftab) || x_ftab[f].xf_flags & XF_NOBIND) {
- bi_errorf("%s: no such function", a2);
- return 1;
- }
-#if 0 /* This breaks the bind commands that map arrow keys */
- if (f == XFUNC_meta1)
- x_prefix1 = key;
- if (f == XFUNC_meta2)
- x_prefix2 = key;
-#endif /* 0 */
- } else {
- f = XFUNC_ins_string;
- m2 = x_mapin(a2);
- sp = str_save(m2, AEDIT);
- }
-
- if (x_tab[prefix][key] == XFUNC_ins_string && x_atab[prefix][key])
- afree((void *)x_atab[prefix][key], AEDIT);
- x_tab[prefix][key] = f;
- x_atab[prefix][key] = sp;
-
- return 0;
-}
-
-void
-x_init_emacs()
-{
- register int i, j;
-
- ainit(AEDIT);
- x_nextcmd = -1;
-
- x_tab = (Findex (*)[X_TABSZ]) alloc(sizeofN(*x_tab, X_NTABS), AEDIT);
- for (j = 0; j < X_TABSZ; j++)
- x_tab[0][j] = XFUNC_insert;
- for (i = 1; i < X_NTABS; i++)
- for (j = 0; j < X_TABSZ; j++)
- x_tab[i][j] = XFUNC_error;
- for (i = 0; i < NELEM(x_defbindings); i++)
- x_tab[x_defbindings[i].xdb_tab][x_defbindings[i].xdb_char]
- = x_defbindings[i].xdb_func;
-
- x_atab = (char *(*)[X_TABSZ]) alloc(sizeofN(*x_atab, X_NTABS), AEDIT);
- for (i = 1; i < X_NTABS; i++)
- for (j = 0; j < X_TABSZ; j++)
- x_atab[i][j] = NULL;
-}
-
-void
-x_emacs_keys(ec)
- X_chars *ec;
-{
- x_tab[0][ec->erase] = XFUNC_del_back;
- x_tab[0][ec->kill] = XFUNC_del_line;
- x_tab[0][ec->werase] = XFUNC_del_bword;
- x_tab[0][ec->intr] = XFUNC_abort;
- x_tab[0][ec->quit] = XFUNC_noop;
- x_tab[1][ec->erase] = XFUNC_del_bword;
-}
-
-static int
-x_set_mark(c)
- int c;
-{
- xmp = xcp;
- return KSTD;
-}
-
-static int
-x_kill_region(c)
- int c;
-{
- int rsize;
- char *xr;
-
- if (xmp == NULL) {
- x_e_putc(BEL);
- return KSTD;
- }
- if (xmp > xcp) {
- rsize = xmp - xcp;
- xr = xcp;
- } else {
- rsize = xcp - xmp;
- xr = xmp;
- }
- x_goto(xr);
- x_delete(rsize, TRUE);
- xmp = xr;
- return KSTD;
-}
-
-static int
-x_xchg_point_mark(c)
- int c;
-{
- char *tmp;
-
- if (xmp == NULL) {
- x_e_putc(BEL);
- return KSTD;
- }
- tmp = xmp;
- xmp = xcp;
- x_goto( tmp );
- return KSTD;
-}
-
-static int
-x_version(c)
- int c;
-{
- char *o_xbuf = xbuf, *o_xend = xend;
- char *o_xbp = xbp, *o_xep = xep, *o_xcp = xcp;
- int lim = x_lastcp() - xbp;
-
- xbuf = xbp = xcp = (char *) ksh_version + 4;
- xend = xep = (char *) ksh_version + 4 + strlen(ksh_version + 4);
- x_redraw(lim);
- x_flush();
-
- c = x_e_getc();
- xbuf = o_xbuf;
- xend = o_xend;
- xbp = o_xbp;
- xep = o_xep;
- xcp = o_xcp;
- x_redraw(strlen(ksh_version));
-
- if (c < 0)
- return KSTD;
- /* This is what at&t ksh seems to do... Very bizarre */
- if (c != ' ')
- x_e_ungetc(c);
-
- return KSTD;
-}
-
-static int
-x_noop(c)
- int c;
-{
- return KSTD;
-}
-
-#ifdef SILLY
-static int
-x_game_of_life(c)
- int c;
-{
- char newbuf [256+1];
- register char *ip, *op;
- int i, len;
-
- i = xep - xbuf;
- *xep = 0;
- len = x_size_str(xbuf);
- xcp = xbp = xbuf;
- memmove(newbuf+1, xbuf, i);
- newbuf[0] = 'A';
- newbuf[i] = 'A';
- for (ip = newbuf+1, op = xbuf; --i >= 0; ip++, op++) {
- /* Empty space */
- if (*ip < '@' || *ip == '_' || *ip == 0x7F) {
- /* Two adults, make whoopee */
- if (ip[-1] < '_' && ip[1] < '_') {
- /* Make kid look like parents. */
- *op = '`' + ((ip[-1] + ip[1])/2)%32;
- if (*op == 0x7F) /* Birth defect */
- *op = '`';
- }
- else
- *op = ' '; /* nothing happens */
- continue;
- }
- /* Child */
- if (*ip > '`') {
- /* All alone, dies */
- if (ip[-1] == ' ' && ip[1] == ' ')
- *op = ' ';
- else /* Gets older */
- *op = *ip-'`'+'@';
- continue;
- }
- /* Adult */
- /* Overcrowded, dies */
- if (ip[-1] >= '@' && ip[1] >= '@') {
- *op = ' ';
- continue;
- }
- *op = *ip;
- }
- *op = 0;
- x_redraw(len);
- return KSTD;
-}
-#endif
-
-/*
- * File/command name completion routines
- */
-
-
-static int
-x_comp_comm(c)
- int c;
-{
- do_complete(XCF_COMMAND, CT_COMPLETE);
- return KSTD;
-}
-static int
-x_list_comm(c)
- int c;
-{
- do_complete(XCF_COMMAND, CT_LIST);
- return KSTD;
-}
-static int
-x_complete(c)
- int c;
-{
- do_complete(XCF_COMMAND_FILE, CT_COMPLETE);
- return KSTD;
-}
-static int
-x_enumerate(c)
- int c;
-{
- do_complete(XCF_COMMAND_FILE, CT_LIST);
- return KSTD;
-}
-static int
-x_comp_file(c)
- int c;
-{
- do_complete(XCF_FILE, CT_COMPLETE);
- return KSTD;
-}
-static int
-x_list_file(c)
- int c;
-{
- do_complete(XCF_FILE, CT_LIST);
- return KSTD;
-}
-static int
-x_comp_list(c)
- int c;
-{
- do_complete(XCF_COMMAND_FILE, CT_COMPLIST);
- return KSTD;
-}
-static int
-x_expand(c)
- int c;
-{
- char **words;
- int nwords = 0;
- int start, end;
- int is_command;
- int i;
-
- nwords = x_cf_glob(XCF_FILE,
- xbuf, xep - xbuf, xcp - xbuf,
- &start, &end, &words, &is_command);
-
- if (nwords == 0) {
- x_e_putc(BEL);
- return KSTD;
- }
-
- x_goto(xbuf + start);
- x_delete(end - start, FALSE);
- for (i = 0; i < nwords; i++)
- if (x_ins(words[i]) < 0 || (i < nwords - 1 && x_ins(space) < 0))
- {
- x_e_putc(BEL);
- return KSTD;
- }
-
- return KSTD;
-}
-
-/* type == 0 for list, 1 for complete and 2 for complete-list */
-static void
-do_complete(flags, type)
- int flags; /* XCF_{COMMAND,FILE,COMMAND_FILE} */
- Comp_type type;
-{
- char **words;
- int nwords = 0;
- int start, end;
- int is_command;
- int do_glob = 1;
- Comp_type t = type;
- char *comp_word = (char *) 0;
-
- if (type == CT_COMPLIST) {
- do_glob = 0;
- /* decide what we will do */
- nwords = x_cf_glob(flags,
- xbuf, xep - xbuf, xcp - xbuf,
- &start, &end, &words, &is_command);
- if (nwords > 0) {
- if (nwords > 1) {
- int len = x_longest_prefix(nwords, words);
-
- t = CT_LIST;
- /* Do completion if prefix matches original
- * prefix (ie, no globbing chars), otherwise
- * don't bother
- */
- if (strncmp(words[0], xbuf + start, end - start)
- == 0)
- comp_word = str_nsave(words[0], len,
- ATEMP);
- else
- type = CT_LIST;
- /* Redo globing to show full paths if this
- * is a command.
- */
- if (is_command) {
- do_glob = 1;
- x_free_words(nwords, words);
- }
- } else
- type = t = CT_COMPLETE;
- }
- }
- if (do_glob)
- nwords = x_cf_glob(flags | (t == CT_LIST ? XCF_FULLPATH : 0),
- xbuf, xep - xbuf, xcp - xbuf,
- &start, &end, &words, &is_command);
- if (nwords == 0) {
- x_e_putc(BEL);
- return;
- }
- switch (type) {
- case CT_LIST:
- x_print_expansions(nwords, words, is_command);
- x_redraw(0);
- break;
-
- case CT_COMPLIST:
- /* Only get here if nwords > 1 && comp_word is set */
- {
- int olen = end - start;
- int nlen = strlen(comp_word);
-
- x_print_expansions(nwords, words, is_command);
- xcp = xbuf + end;
- x_do_ins(comp_word + olen, nlen - olen);
- x_redraw(0);
- }
- break;
-
- case CT_COMPLETE:
- {
- int nlen = x_longest_prefix(nwords, words);
-
- if (nlen > 0) {
- x_goto(xbuf + start);
- x_delete(end - start, FALSE);
- words[0][nlen] = '\0';
- x_ins(words[0]);
- /* If single match is not a directory, add a
- * space to the end...
- */
- if (nwords == 1
- && !ISDIRSEP(words[0][nlen - 1]))
- x_ins(space);
- } else
- x_e_putc(BEL);
- }
- break;
- }
-}
-
-/* NAME:
- * x_adjust - redraw the line adjusting starting point etc.
- *
- * DESCRIPTION:
- * This function is called when we have exceeded the bounds
- * of the edit window. It increments x_adj_done so that
- * functions like x_ins and x_delete know that we have been
- * called and can skip the x_bs() stuff which has already
- * been done by x_redraw.
- *
- * RETURN VALUE:
- * None
- */
-
-static void
-x_adjust()
-{
- x_adj_done++; /* flag the fact that we were called. */
- /*
- * we had a problem if the prompt length > xx_cols / 2
- */
- if ((xbp = xcp - (x_displen / 2)) < xbuf)
- xbp = xbuf;
- xlp_valid = FALSE;
- x_redraw(xx_cols);
- x_flush();
-}
-
-static int unget_char = -1;
-
-static void
-x_e_ungetc(c)
- int c;
-{
- unget_char = c;
-}
-
-static int
-x_e_getc()
-{
- int c;
-
- if (unget_char >= 0) {
- c = unget_char;
- unget_char = -1;
- } else {
- if (macroptr) {
- c = *macroptr++;
- if (!*macroptr)
- macroptr = (char *) 0;
- } else
- c = x_getc();
- }
-
- return c <= CHARMASK ? c : (c & CHARMASK);
-}
-
-static void
-x_e_putc(c)
- int c;
-{
- if (c == '\r' || c == '\n')
- x_col = 0;
- if (x_col < xx_cols)
- {
- x_putc(c);
- switch(c)
- {
- case BEL:
- break;
- case '\r':
- case '\n':
- break;
- case '\b':
- x_col--;
- break;
- default:
- x_col++;
- break;
- }
- }
- if (x_adj_ok && (x_col < 0 || x_col >= (xx_cols - 2)))
- {
- x_adjust();
- }
-}
-
-#ifdef DEBUG
-static int
-x_debug_info(c)
- int c;
-{
- x_flush();
- shellf("\nksh debug:\n");
- shellf("\tx_col == %d,\t\tx_cols == %d,\tx_displen == %d\n",
- x_col, xx_cols, x_displen);
- shellf("\txcp == 0x%lx,\txep == 0x%lx\n", (long) xcp, (long) xep);
- shellf("\txbp == 0x%lx,\txbuf == 0x%lx\n", (long) xbp, (long) xbuf);
- shellf("\txlp == 0x%lx\n", (long) xlp);
- shellf("\txlp == 0x%lx\n", (long) x_lastcp());
- shellf(newline);
- x_redraw(-1);
- return 0;
-}
-#endif
-
-static void
-x_e_puts(s)
- const char *s;
-{
- register int adj = x_adj_done;
-
- while (*s && adj == x_adj_done)
- x_e_putc(*s++);
-}
-
-/* NAME:
- * x_set_arg - set an arg value for next function
- *
- * DESCRIPTION:
- * This is a simple implementation of M-[0-9].
- *
- * RETURN VALUE:
- * KSTD
- */
-
-static int
-x_set_arg(c)
- int c;
-{
- int n = 0;
- int first = 1;
-
- c &= CHARMASK; /* strip command prefix */
- for (; c >= 0 && isdigit(c); c = x_e_getc(), first = 0)
- n = n * 10 + (c - '0');
- if (c < 0 || first) {
- x_e_putc(BEL);
- x_arg = 1;
- x_arg_defaulted = 1;
- } else {
- x_e_ungetc(c);
- x_arg = n;
- x_arg_defaulted = 0;
- }
- return KSTD;
-}
-
-
-/* Comment or uncomment the current line. */
-static int
-x_comment(c)
- int c;
-{
- int oldsize = x_size_str(xbuf);
- int len = xep - xbuf;
- int ret = x_do_comment(xbuf, xend - xbuf, &len);
-
- if (ret < 0)
- x_e_putc(BEL);
- else {
- xep = xbuf + len;
- *xep = '\0';
- xcp = xbp = xbuf;
- x_redraw(oldsize);
- if (ret > 0)
- return x_newline('\n');
- }
- return KSTD;
-}
-
-
-/* NAME:
- * x_prev_histword - recover word from prev command
- *
- * DESCRIPTION:
- * This function recovers the last word from the previous
- * command and inserts it into the current edit line. If a
- * numeric arg is supplied then the n'th word from the
- * start of the previous command is used.
- *
- * Bound to M-.
- *
- * RETURN VALUE:
- * KSTD
- */
-
-static int
-x_prev_histword(c)
- int c;
-{
- register char *rcp;
- char *cp;
- char **hp;
-
- hp = x_histp-1;
- if (hp < history || hp > histptr)
- {
- x_e_putc(BEL);
- return KSTD;
- }
- cp = *hp;
- if (x_arg_defaulted) {
- rcp = &cp[strlen(cp) - 1];
- /*
- * ignore white-space after the last word
- */
- while (rcp > cp && is_cfs(*rcp))
- rcp--;
- while (rcp > cp && !is_cfs(*rcp))
- rcp--;
- if (is_cfs(*rcp))
- rcp++;
- x_ins(rcp);
- } else {
- int c;
-
- rcp = cp;
- /*
- * ignore white-space at start of line
- */
- while (*rcp && is_cfs(*rcp))
- rcp++;
- while (x_arg-- > 1)
- {
- while (*rcp && !is_cfs(*rcp))
- rcp++;
- while (*rcp && is_cfs(*rcp))
- rcp++;
- }
- cp = rcp;
- while (*rcp && !is_cfs(*rcp))
- rcp++;
- c = *rcp;
- *rcp = '\0';
- x_ins(cp);
- *rcp = c;
- }
- return KSTD;
-}
-
-/* Uppercase N(1) words */
-static int
-x_fold_upper(c)
- int c;
-{
- return x_fold_case('U');
-}
-
-/* Lowercase N(1) words */
-static int
-x_fold_lower(c)
- int c;
-{
- return x_fold_case('L');
-}
-
-/* Lowercase N(1) words */
-static int
-x_fold_capitialize(c)
- int c;
-{
- return x_fold_case('C');
-}
-
-/* NAME:
- * x_fold_case - convert word to UPPER/lower/Capitial case
- *
- * DESCRIPTION:
- * This function is used to implement M-U,M-u,M-L,M-l,M-C and M-c
- * to UPPER case, lower case or Capitalize words.
- *
- * RETURN VALUE:
- * None
- */
-
-static int
-x_fold_case(c)
- int c;
-{
- char *cp = xcp;
-
- if (cp == xep) {
- x_e_putc(BEL);
- return KSTD;
- }
- while (x_arg--) {
- /*
- * fisrt skip over any white-space
- */
- while (cp != xep && is_mfs(*cp))
- cp++;
- /*
- * do the first char on its own since it may be
- * a different action than for the rest.
- */
- if (cp != xep) {
- if (c == 'L') { /* lowercase */
- if (isupper(*cp))
- *cp = tolower(*cp);
- } else { /* uppercase, capitialize */
- if (islower(*cp))
- *cp = toupper(*cp);
- }
- cp++;
- }
- /*
- * now for the rest of the word
- */
- while (cp != xep && !is_mfs(*cp)) {
- if (c == 'U') { /* uppercase */
- if (islower(*cp))
- *cp = toupper(*cp);
- } else { /* lowercase, capitialize */
- if (isupper(*cp))
- *cp = tolower(*cp);
- }
- cp++;
- }
- }
- x_goto(cp);
- return KSTD;
-}
-
-/* NAME:
- * x_lastcp - last visible char
- *
- * SYNOPSIS:
- * x_lastcp()
- *
- * DESCRIPTION:
- * This function returns a pointer to that char in the
- * edit buffer that will be the last displayed on the
- * screen. The sequence:
- *
- * for (cp = x_lastcp(); cp > xcp; cp)
- * x_bs(*--cp);
- *
- * Will position the cursor correctly on the screen.
- *
- * RETURN VALUE:
- * cp or NULL
- */
-
-static char *
-x_lastcp()
-{
- register char *rcp;
- register int i;
-
- if (!xlp_valid)
- {
- for (i = 0, rcp = xbp; rcp < xep && i < x_displen; rcp++)
- i += x_size(*rcp);
- xlp = rcp;
- }
- xlp_valid = TRUE;
- return (xlp);
-}
-
-#endif /* EDIT */
diff --git a/bin/pdksh/eval.c b/bin/pdksh/eval.c
deleted file mode 100644
index 292294d08ee..00000000000
--- a/bin/pdksh/eval.c
+++ /dev/null
@@ -1,1361 +0,0 @@
-/* $OpenBSD: eval.c,v 1.4 1997/06/19 13:58:40 kstailey Exp $ */
-
-/*
- * Expansion - quoting, separation, substitution, globbing
- */
-
-#include "sh.h"
-#include <pwd.h>
-#include "ksh_dir.h"
-#include "ksh_stat.h"
-
-/*
- * string expansion
- *
- * first pass: quoting, IFS separation, ~, ${}, $() and $(()) substitution.
- * second pass: alternation ({,}), filename expansion (*?[]).
- */
-
-/* expansion generator state */
-typedef struct Expand {
- /* int type; */ /* see expand() */
- const char *str; /* string */
- union {
- const char **strv;/* string[] */
- struct shf *shf;/* file */
- } u; /* source */
- struct tbl *var; /* variable in ${var..} */
- short split; /* split "$@" / call waitlast $() */
-} Expand;
-
-#define XBASE 0 /* scanning original */
-#define XSUB 1 /* expanding ${} string */
-#define XARGSEP 2 /* ifs0 between "$*" */
-#define XARG 3 /* expanding $*, $@ */
-#define XCOM 4 /* expanding $() */
-#define XNULLSUB 5 /* "$@" when $# is 0 (don't generate word) */
-
-/* States used for field splitting */
-#define IFS_WORD 0 /* word has chars (or quotes) */
-#define IFS_WS 1 /* have seen IFS white-space */
-#define IFS_NWS 2 /* have seen IFS non-white-space */
-
-static int varsub ARGS((Expand *xp, char *sp, char *word, int *stypep));
-static int comsub ARGS((Expand *xp, char *cp));
-static char *trimsub ARGS((char *str, char *pat, int how));
-static void glob ARGS((char *cp, XPtrV *wp, int markdirs));
-static void globit ARGS((XString *xs, char **xpp, char *sp, XPtrV *wp,
- int check));
-static char *maybe_expand_tilde ARGS((char *p, XString *dsp, char **dpp,
- int isassign));
-static char *tilde ARGS((char *acp));
-static char *homedir ARGS((char *name));
-#ifdef BRACE_EXPAND
-static void alt_expand ARGS((XPtrV *wp, char *start, char *exp_start,
- char *end, int fdo));
-#endif
-
-/* compile and expand word */
-char *
-substitute(cp, f)
- const char *cp;
- int f;
-{
- struct source *s, *sold;
-
- sold = source;
- s = pushs(SWSTR, ATEMP);
- s->start = s->str = cp;
- source = s;
- if (yylex(ONEWORD) != LWORD)
- internal_errorf(1, "substitute");
- source = sold;
- afree(s, ATEMP);
- return evalstr(yylval.cp, f);
-}
-
-/*
- * expand arg-list
- */
-char **
-eval(ap, f)
- register char **ap;
- int f;
-{
- XPtrV w;
-
- if (*ap == NULL)
- return ap;
- XPinit(w, 32);
- XPput(w, NULL); /* space for shell name */
-#ifdef SHARPBANG
- XPput(w, NULL); /* and space for one arg */
-#endif
- while (*ap != NULL)
- expand(*ap++, &w, f);
- XPput(w, NULL);
-#ifdef SHARPBANG
- return (char **) XPclose(w) + 2;
-#else
- return (char **) XPclose(w) + 1;
-#endif
-}
-
-/*
- * expand string
- */
-char *
-evalstr(cp, f)
- char *cp;
- int f;
-{
- XPtrV w;
-
- XPinit(w, 1);
- expand(cp, &w, f);
- cp = (XPsize(w) == 0) ? null : (char*) *XPptrv(w);
- XPfree(w);
- return cp;
-}
-
-/*
- * expand string - return only one component
- * used from iosetup to expand redirection files
- */
-char *
-evalonestr(cp, f)
- register char *cp;
- int f;
-{
- XPtrV w;
-
- XPinit(w, 1);
- expand(cp, &w, f);
- switch (XPsize(w)) {
- case 0:
- cp = null;
- break;
- case 1:
- cp = (char*) *XPptrv(w);
- break;
- default:
- cp = evalstr(cp, f&~DOGLOB);
- break;
- }
- XPfree(w);
- return cp;
-}
-
-/* for nested substitution: ${var:=$var2} */
-typedef struct SubType {
- short stype; /* [=+-?%#] action after expanded word */
- short base; /* begin position of expanded word */
- short f; /* saved value of f (DOPAT, etc) */
- struct tbl *var; /* variable for ${var..} */
- short quote; /* saved value of quote (for ${..[%#]..}) */
- struct SubType *prev; /* old type */
- struct SubType *next; /* poped type (to avoid re-allocating) */
-} SubType;
-
-void
-expand(cp, wp, f)
- char *cp; /* input word */
- register XPtrV *wp; /* output words */
- int f; /* DO* flags */
-{
- register int UNINITIALIZED(c);
- register int type; /* expansion type */
- register int quote = 0; /* quoted */
- XString ds; /* destination string */
- register char *dp, *sp; /* dest., source */
- int fdo, word; /* second pass flags; have word */
- int doblank; /* field spliting of parameter/command subst */
- Expand x; /* expansion variables */
- SubType st_head, *st;
- int UNINITIALIZED(newlines); /* For trailing newlines in COMSUB */
- int saw_eq, tilde_ok;
- int make_magic;
-
- if (cp == NULL)
- internal_errorf(1, "expand(NULL)");
- /* for alias, readonly, set, typeset commands */
- if ((f & DOVACHECK) && is_wdvarassign(cp)) {
- f &= ~(DOVACHECK|DOBLANK|DOGLOB|DOTILDE);
- f |= DOASNTILDE;
- }
- if (Flag(FNOGLOB))
- f &= ~DOGLOB;
- if (Flag(FMARKDIRS))
- f |= DOMARKDIRS;
-#ifdef BRACE_EXPAND
- if (Flag(FBRACEEXPAND) && (f & DOGLOB))
- f |= DOBRACE_;
-#endif /* BRACE_EXPAND */
-
- Xinit(ds, dp, 128, ATEMP); /* init dest. string */
- type = XBASE;
- sp = cp;
- fdo = 0;
- saw_eq = 0;
- tilde_ok = (f & (DOTILDE|DOASNTILDE)) ? 1 : 0; /* must be 1/0 */
- doblank = 0;
- make_magic = 0;
- word = (f&DOBLANK) ? IFS_WS : IFS_WORD;
- st_head.next = (SubType *) 0;
- st = &st_head;
-
- while (1) {
- Xcheck(ds, dp);
-
- switch (type) {
- case XBASE: /* original prefixed string */
- c = *sp++;
- switch (c) {
- case EOS:
- c = 0;
- break;
- case CHAR:
- c = *sp++;
- break;
- case QCHAR:
- quote |= 2; /* temporary quote */
- c = *sp++;
- break;
- case OQUOTE:
- word = IFS_WORD;
- tilde_ok = 0;
- quote = 1;
- continue;
- case CQUOTE:
- quote = 0;
- continue;
- case COMSUB:
- tilde_ok = 0;
- if (f & DONTRUNCOMMAND) {
- word = IFS_WORD;
- *dp++ = '$'; *dp++ = '(';
- while (*sp != '\0') {
- Xcheck(ds, dp);
- *dp++ = *sp++;
- }
- *dp++ = ')';
- } else {
- type = comsub(&x, sp);
- if (type == XCOM && (f&DOBLANK))
- doblank++;
- sp = strchr(sp, 0) + 1;
- newlines = 0;
- }
- continue;
- case EXPRSUB:
- word = IFS_WORD;
- tilde_ok = 0;
- if (f & DONTRUNCOMMAND) {
- *dp++ = '$'; *dp++ = '('; *dp++ = '(';
- while (*sp != '\0') {
- Xcheck(ds, dp);
- *dp++ = *sp++;
- }
- *dp++ = ')'; *dp++ = ')';
- } else {
- struct tbl v;
- char *p;
-
- v.flag = DEFINED|ISSET|INTEGER;
- v.type = 10; /* not default */
- v.name[0] = '\0';
- v_evaluate(&v, substitute(sp, 0),
- FALSE);
- sp = strchr(sp, 0) + 1;
- for (p = str_val(&v); *p; ) {
- Xcheck(ds, dp);
- *dp++ = *p++;
- }
- }
- continue;
- case OSUBST: /* ${{#}var{:}[=+-?#%]word} */
- /* format is:
- * OSUBST plain-variable-part \0
- * compiled-word-part CSUBST
- * This is were all syntax checking gets done...
- */
- {
- char *varname = sp;
- int stype;
-
- sp = strchr(sp, '\0') + 1; /* skip variable */
- type = varsub(&x, varname, sp, &stype);
- if (type < 0) {
- char endc;
- char *str, *end;
-
- end = (char *) wdscan(sp, CSUBST);
- endc = *end;
- *end = EOS;
- str = snptreef((char *) 0, 64, "%S",
- varname - 1);
- *end = endc;
- errorf("%s: bad substitution", str);
- }
- if (f&DOBLANK)
- doblank++;
- tilde_ok = 0;
- if (type == XBASE) { /* expand? */
- if (!st->next) {
- SubType *newst;
-
- newst = (SubType *) alloc(
- sizeof(SubType), ATEMP);
- newst->next = (SubType *) 0;
- newst->prev = st;
- st->next = newst;
- }
- st = st->next;
- st->stype = stype;
- st->base = Xsavepos(ds, dp);
- st->f = f;
- st->var = x.var;
- st->quote = quote;
- /* skip qualifier(s) */
- if (stype) {
- sp += 2;
- /* :[-+=?] or double [#%] */
- if (stype & 0x80)
- sp += 2;
- }
- switch (stype & 0x7f) {
- case '#':
- case '%':
- /* ! DOBLANK,DOBRACE_,DOTILDE */
- f = DOPAT | (f&DONTRUNCOMMAND)
- | DOTEMP_;
- quote = 0;
- break;
- case '=':
- /* Enabling tilde expansion
- * after :'s here is
- * non-standard ksh, but is
- * consistent with rules for
- * other assignments. Not
- * sure what POSIX thinks of
- * this.
- * Not doing tilde expansion
- * for integer variables is a
- * non-POSIX thing - makes
- * sense though, since ~ is
- * a arithmetic operator.
- */
-#if !defined(__hppa) || __GNUC__ != 2 /* gcc 2.3.3 on hp-pa dies on this - ifdef goes away as soon as I get a new version of gcc.. */
- if (!(x.var->flag & INTEGER))
- f |= DOASNTILDE|DOTILDE;
- f |= DOTEMP_;
-#else
- f |= DOTEMP_|DOASNTILDE|DOTILDE;
-#endif
- /* These will be done after the
- * value has been assigned.
- */
- f &= ~(DOBLANK|DOGLOB|DOBRACE_);
- tilde_ok = 1;
- break;
- case '?':
- f &= ~DOBLANK;
- f |= DOTEMP_;
- /* fall through */
- default:
- /* Enable tilde expansion */
- tilde_ok = 1;
- f |= DOTILDE;
- }
- } else
- /* skip word */
- sp = (char *) wdscan(sp, CSUBST);
- continue;
- }
- case CSUBST: /* only get here if expanding word */
- tilde_ok = 0; /* in case of ${unset:-} */
- *dp = '\0';
- quote = st->quote;
- f = st->f;
- if (f&DOBLANK)
- doblank--;
- switch (st->stype&0x7f) {
- case '#':
- case '%':
- dp = Xrestpos(ds, dp, st->base);
- /* Must use st->var since calling
- * global would break things
- * like x[i+=1].
- */
- x.str = trimsub(str_val(st->var),
- dp, st->stype);
- type = XSUB;
- if (f&DOBLANK)
- doblank++;
- st = st->prev;
- continue;
- case '=':
- if (st->var->flag & RDONLY)
- /* XXX POSIX says this is only
- * fatal for special builtins
- */
- errorf("%s: is read only",
- st->var->name);
- /* Restore our position and substitute
- * the value of st->var (may not be
- * the assigned value in the presence
- * of integer/right-adj/etc attributes).
- */
- dp = Xrestpos(ds, dp, st->base);
- /* Must use st->var since calling
- * global would cause with things
- * like x[i+=1] to be evaluated twice.
- */
- setstr(st->var, debunk(
- (char *) alloc(strlen(dp) + 1,
- ATEMP), dp));
- x.str = str_val(st->var);
- type = XSUB;
- if (f&DOBLANK)
- doblank++;
- st = st->prev;
- continue;
- case '?':
- {
- char *s = Xrestpos(ds, dp, st->base);
-
- errorf("%s: %s", st->var->name,
- dp == s ?
- "parameter null or not set"
- : (debunk(s, s), s));
- }
- }
- st = st->prev;
- type = XBASE;
- continue;
-
- case OPAT: /* open pattern: *(foo|bar) */
- /* Next char is the type of pattern */
- make_magic = 1;
- c = *sp++ + 0x80;
- break;
-
- case SPAT: /* pattern seperator (|) */
- make_magic = 1;
- c = '|';
- break;
-
- case CPAT: /* close pattern */
- make_magic = 1;
- c = /*(*/ ')';
- break;
- }
- break;
-
- case XNULLSUB:
- /* Special case for "$@" (and "${foo[@]}") - no
- * word is generated if $# is 0 (unless there is
- * other stuff inside the quotes).
- */
- type = XBASE;
- if (f&DOBLANK) {
- doblank--;
- /* not really correct: x=; "$x$@" should
- * generate a null argument and
- * set A; "${@:+}" shouldn't.
- */
- if (dp == Xstring(ds, dp))
- word = IFS_WS;
- }
- continue;
-
- case XSUB:
- if ((c = *x.str++) == 0) {
- type = XBASE;
- if (f&DOBLANK)
- doblank--;
- continue;
- }
- break;
-
- case XARGSEP:
- type = XARG;
- quote = 1;
- case XARG:
- if ((c = *x.str++) == '\0') {
- /* force null words to be created so
- * set -- '' 2 ''; foo "$@" will do
- * the right thing
- */
- if (quote && x.split)
- word = IFS_WORD;
- if ((x.str = *x.u.strv++) == NULL) {
- type = XBASE;
- if (f&DOBLANK)
- doblank--;
- continue;
- }
- c = ifs0;
- if (c == 0) {
- if (quote && !x.split)
- continue;
- c = ' ';
- }
- if (quote && x.split) {
- /* terminate word for "$@" */
- type = XARGSEP;
- quote = 0;
- }
- }
- break;
-
- case XCOM:
- if (newlines) { /* Spit out saved nl's */
- c = '\n';
- --newlines;
- } else {
- while ((c = shf_getc(x.u.shf)) == 0 || c == '\n')
- if (c == '\n')
- newlines++; /* Save newlines */
- if (newlines && c != EOF) {
- shf_ungetc(c, x.u.shf);
- c = '\n';
- --newlines;
- }
- }
- if (c == EOF) {
- newlines = 0;
- shf_close(x.u.shf);
- if (x.split)
- subst_exstat = waitlast();
- type = XBASE;
- if (f&DOBLANK)
- doblank--;
- continue;
- }
- break;
- }
-
- /* check for end of word or IFS separation */
- if (c == 0 || (!quote && (f & DOBLANK) && doblank && !make_magic
- && ctype(c, C_IFS)))
- {
- /* How words are broken up:
- * | value of c
- * word | ws nws 0
- * -----------------------------------
- * IFS_WORD w/WS w/NWS w
- * IFS_WS -/WS w/NWS -
- * IFS_NWS -/NWS w/NWS w
- * (w means generate a word)
- * Note that IFS_NWS/0 generates a word (at&t ksh
- * doesn't do this, but POSIX does).
- */
- if (word == IFS_WORD
- || (!ctype(c, C_IFSWS) && (c || word == IFS_NWS)))
- {
- char *p;
-
- *dp++ = '\0';
- p = Xclose(ds, dp);
-#ifdef BRACE_EXPAND
- if (fdo & DOBRACE_)
- /* also does globbing */
- alt_expand(wp, p, p,
- p + Xlength(ds, (dp - 1)),
- fdo | (f & DOMARKDIRS));
- else
-#endif /* BRACE_EXPAND */
- if (fdo & DOGLOB)
- glob(p, wp, f & DOMARKDIRS);
- else if ((f & DOPAT) || !(fdo & DOMAGIC_))
- XPput(*wp, p);
- else
- XPput(*wp, debunk(p, p));
- fdo = 0;
- saw_eq = 0;
- tilde_ok = (f & (DOTILDE|DOASNTILDE)) ? 1 : 0;
- if (c != 0)
- Xinit(ds, dp, 128, ATEMP);
- }
- if (c == 0)
- return;
- if (word != IFS_NWS)
- word = ctype(c, C_IFSWS) ? IFS_WS : IFS_NWS;
- } else {
- /* age tilde_ok info - ~ code tests second bit */
- tilde_ok <<= 1;
- /* mark any special second pass chars */
- if (!quote)
- switch (c) {
- case '[':
- case NOT:
- case '-':
- case ']':
- /* For character classes - doesn't hurt
- * to have magic !,-,]'s outside of
- * [...] expressions.
- */
- if (f & (DOPAT | DOGLOB)) {
- fdo |= DOMAGIC_;
- if (c == '[')
- fdo |= f & DOGLOB;
- *dp++ = MAGIC;
- }
- break;
- case '*':
- case '?':
- if (f & (DOPAT | DOGLOB)) {
- fdo |= DOMAGIC_ | (f & DOGLOB);
- *dp++ = MAGIC;
- }
- break;
-#ifdef BRACE_EXPAND
- case OBRACE:
- case ',':
- case CBRACE:
- if ((f & DOBRACE_) && (c == OBRACE
- || (fdo & DOBRACE_)))
- {
- fdo |= DOBRACE_|DOMAGIC_;
- *dp++ = MAGIC;
- }
- break;
-#endif /* BRACE_EXPAND */
- case '=':
- /* Note first unquoted = for ~ */
- if (!(f & DOTEMP_) && !saw_eq) {
- saw_eq = 1;
- tilde_ok = 1;
- }
- break;
- case PATHSEP: /* : */
- /* Note unquoted : for ~ */
- if (!(f & DOTEMP_) && (f & DOASNTILDE))
- tilde_ok = 1;
- break;
- case '~':
- /* tilde_ok is reset whenever
- * any of ' " $( $(( ${ } are seen.
- * Note that tilde_ok must be preserved
- * through the sequence ${A=a=}~
- */
- if (type == XBASE
- && (f & (DOTILDE|DOASNTILDE))
- && (tilde_ok & 2))
- {
- char *p, *dp_x;
-
- dp_x = dp;
- p = maybe_expand_tilde(sp,
- &ds, &dp_x,
- f & DOASNTILDE);
- if (p) {
- if (dp != dp_x)
- word = IFS_WORD;
- dp = dp_x;
- sp = p;
- continue;
- }
- }
- break;
- }
- else
- quote &= ~2; /* undo temporary */
-
- if (make_magic) {
- make_magic = 0;
- fdo |= DOMAGIC_ | (f & DOGLOB);
- *dp++ = MAGIC;
- } else if (ISMAGIC(c)) {
- fdo |= DOMAGIC_;
- *dp++ = MAGIC;
- }
- *dp++ = c; /* save output char */
- word = IFS_WORD;
- }
- }
-}
-
-/*
- * Prepare to generate the string returned by ${} substitution.
- */
-static int
-varsub(xp, sp, word, stypep)
- Expand *xp;
- char *sp;
- char *word;
- int *stypep;
-{
- int c;
- int state; /* next state: XBASE, XARG, XSUB, XNULLSUB */
- int stype; /* substitution type */
- char *p;
- struct tbl *vp;
-
- if (sp[0] == '\0') /* Bad variable name */
- return -1;
-
- xp->var = (struct tbl *) 0;
-
- /* ${#var}, string length or array size */
- if (sp[0] == '#' && (c = sp[1]) != '\0') {
- int zero_ok = 0;
-
- /* Can't have any modifiers for ${#...} */
- if (*word != CSUBST)
- return -1;
- sp++;
- /* Check for size of array */
- if ((p=strchr(sp,'[')) && (p[1]=='*'||p[1]=='@') && p[2]==']') {
- c = 0;
- vp = global(arrayname(sp));
- if (vp->flag & (ISSET|ARRAY))
- zero_ok = 1;
- for (; vp; vp = vp->u.array)
- if (vp->flag&ISSET)
- c = vp->index+1;
- } else if (c == '*' || c == '@')
- c = e->loc->argc;
- else {
- p = str_val(global(sp));
- zero_ok = p != null;
- c = strlen(p);
- }
- if (Flag(FNOUNSET) && c == 0 && !zero_ok)
- errorf("%s: parameter not set", sp);
- *stypep = 0; /* unqualified variable/string substitution */
- xp->str = str_save(ulton((unsigned long)c, 10), ATEMP);
- return XSUB;
- }
-
- /* Check for qualifiers in word part */
- stype = 0;
- c = *word == CHAR ? word[1] : 0;
- if (c == ':') {
- stype = 0x80;
- c = word[2] == CHAR ? word[3] : 0;
- }
- if (ctype(c, C_SUBOP1))
- stype |= c;
- else if (stype) /* :, :# or :% is not ok */
- return -1;
- else if (ctype(c, C_SUBOP2)) {
- stype = c;
- if (word[2] == CHAR && c == word[3])
- stype |= 0x80;
- }
- if (!stype && *word != CSUBST)
- return -1;
- *stypep = stype;
-
- c = sp[0];
- if (c == '*' || c == '@') {
- switch (stype & 0x7f) {
- case '=': /* can't assign to a vector */
- case '%': /* can't trim a vector */
- case '#':
- return -1;
- }
- if (e->loc->argc == 0) {
- xp->str = null;
- state = c == '@' ? XNULLSUB : XSUB;
- } else {
- xp->u.strv = (const char **) e->loc->argv + 1;
- xp->str = *xp->u.strv++;
- xp->split = c == '@'; /* $@ */
- state = XARG;
- }
- } else {
- if ((p=strchr(sp,'[')) && (p[1]=='*'||p[1]=='@') && p[2]==']') {
- XPtrV wv;
-
- switch (stype & 0x7f) {
- case '=': /* can't assign to a vector */
- case '%': /* can't trim a vector */
- case '#':
- return -1;
- }
- XPinit(wv, 32);
- vp = global(arrayname(sp));
- for (; vp; vp = vp->u.array) {
- if (!(vp->flag&ISSET))
- continue;
- XPput(wv, str_val(vp));
- }
- if (XPsize(wv) == 0) {
- xp->str = null;
- state = p[1] == '@' ? XNULLSUB : XSUB;
- XPfree(wv);
- } else {
- XPput(wv, 0);
- xp->u.strv = (const char **) XPptrv(wv);
- xp->str = *xp->u.strv++;
- xp->split = p[1] == '@'; /* ${foo[@]} */
- state = XARG;
- }
- } else {
- /* Can't assign things like $! or $1 */
- if ((stype & 0x7f) == '='
- && (ctype(*sp, C_VAR1) || digit(*sp)))
- return -1;
- xp->var = global(sp);
- xp->str = str_val(xp->var);
- state = XSUB;
- }
- }
-
- c = stype&0x7f;
- /* test the compiler's code generator */
- if (ctype(c, C_SUBOP2) ||
- (((stype&0x80) ? *xp->str=='\0' : xp->str==null) ? /* undef? */
- c == '=' || c == '-' || c == '?' : c == '+'))
- state = XBASE; /* expand word instead of variable value */
- if (Flag(FNOUNSET) && xp->str == null
- && (ctype(c, C_SUBOP2) || (state != XBASE && c != '+')))
- errorf("%s: parameter not set", sp);
- return state;
-}
-
-/*
- * Run the command in $(...) and read its output.
- */
-static int
-comsub(xp, cp)
- register Expand *xp;
- char *cp;
-{
- Source *s, *sold;
- register struct op *t;
- struct shf *shf;
-
- s = pushs(SSTRING, ATEMP);
- s->start = s->str = cp;
- sold = source;
- t = compile(s);
- source = sold;
-
- if (t == NULL)
- return XBASE;
-
- if (t != NULL && t->type == TCOM && /* $(<file) */
- *t->args == NULL && *t->vars == NULL && t->ioact != NULL) {
- register struct ioword *io = *t->ioact;
- char *name;
-
- if ((io->flag&IOTYPE) != IOREAD)
- errorf("funny $() command: %s",
- snptreef((char *) 0, 32, "%R", io));
- shf = shf_open(name = evalstr(io->name, DOTILDE), O_RDONLY, 0,
- SHF_MAPHI|SHF_CLEXEC);
- if (shf == NULL)
- errorf("%s: cannot open $() input", name);
- xp->split = 0; /* no waitlast() */
- } else {
- int ofd1, pv[2];
- openpipe(pv);
- shf = shf_fdopen(pv[0], SHF_RD, (struct shf *) 0);
- ofd1 = savefd(1, 0); /* fd 1 may be closed... */
- ksh_dup2(pv[1], 1, FALSE);
- close(pv[1]);
- execute(t, XFORK|XXCOM|XPIPEO);
- restfd(1, ofd1);
- startlast();
- xp->split = 1; /* waitlast() */
- }
-
- xp->u.shf = shf;
- return XCOM;
-}
-
-/*
- * perform #pattern and %pattern substitution in ${}
- */
-
-static char *
-trimsub(str, pat, how)
- register char *str;
- char *pat;
- int how;
-{
- register char *end = strchr(str, 0);
- register char *p, c;
-
- switch (how&0xff) { /* UCHAR_MAX maybe? */
- case '#': /* shortest at begining */
- for (p = str; p <= end; p++) {
- c = *p; *p = '\0';
- if (gmatch(str, pat, FALSE)) {
- *p = c;
- return p;
- }
- *p = c;
- }
- break;
- case '#'|0x80: /* longest match at begining */
- for (p = end; p >= str; p--) {
- c = *p; *p = '\0';
- if (gmatch(str, pat, FALSE)) {
- *p = c;
- return p;
- }
- *p = c;
- }
- break;
- case '%': /* shortest match at end */
- for (p = end; p >= str; p--) {
- if (gmatch(p, pat, FALSE))
- return str_nsave(str, p - str, ATEMP);
- }
- break;
- case '%'|0x80: /* longest match at end */
- for (p = str; p <= end; p++) {
- if (gmatch(p, pat, FALSE))
- return str_nsave(str, p - str, ATEMP);
- }
- break;
- }
-
- return str; /* no match, return string */
-}
-
-/*
- * glob
- * Name derived from V6's /etc/glob, the program that expanded filenames.
- */
-
-/* XXX cp not const 'cause slashes are temporarily replaced with nulls... */
-static void
-glob(cp, wp, markdirs)
- char *cp;
- register XPtrV *wp;
- int markdirs;
-{
- int oldsize = XPsize(*wp);
-
- if (glob_str(cp, wp, markdirs) == 0)
- XPput(*wp, debunk(cp, cp));
- else
- qsortp(XPptrv(*wp) + oldsize, (size_t)(XPsize(*wp) - oldsize),
- xstrcmp);
-}
-
-#define GF_NONE 0
-#define GF_EXCHECK BIT(0) /* do existance check on file */
-#define GF_GLOBBED BIT(1) /* some globbing has been done */
-#define GF_MARKDIR BIT(2) /* add trailing / to directories */
-
-/* Apply file globbing to cp and store the matching files in wp. Returns
- * the number of matches found.
- */
-int
-glob_str(cp, wp, markdirs)
- char *cp;
- XPtrV *wp;
- int markdirs;
-{
- int oldsize = XPsize(*wp);
- XString xs;
- char *xp;
-
- Xinit(xs, xp, 256, ATEMP);
- globit(&xs, &xp, cp, wp, markdirs ? GF_MARKDIR : GF_NONE);
- Xfree(xs, xp);
-
- return XPsize(*wp) - oldsize;
-}
-
-static void
-globit(xs, xpp, sp, wp, check)
- XString *xs; /* dest string */
- char **xpp; /* ptr to dest end */
- char *sp; /* source path */
- register XPtrV *wp; /* output list */
- int check; /* GF_* flags */
-{
- register char *np; /* next source component */
- char *xp = *xpp;
- char *se;
- char odirsep;
-
- /* This to allow long expansions to be interrupted */
- intrcheck();
-
- if (sp == NULL) { /* end of source path */
- /* We only need to check if the file exists if a pattern
- * is followed by a non-pattern (eg, foo*x/bar; no check
- * is needed for foo* since the match must exist) or if
- * any patterns were expanded and the markdirs option is set.
- * Symlinks make things a bit tricky...
- */
- if ((check & GF_EXCHECK)
- || ((check & GF_MARKDIR) && (check & GF_GLOBBED)))
- {
-#define stat_check() (stat_done ? stat_done : \
- (stat_done = stat(Xstring(*xs, xp), &statb) < 0 \
- ? -1 : 1))
- struct stat lstatb, statb;
- int stat_done = 0; /* -1: failed, 1 ok */
-
- if (lstat(Xstring(*xs, xp), &lstatb) < 0)
- return;
- /* special case for systems which strip trailing
- * slashes from regular files (eg, /etc/passwd/).
- * SunOS 4.1.3 does this...
- */
- if ((check & GF_EXCHECK) && xp > Xstring(*xs, xp)
- && ISDIRSEP(xp[-1]) && !S_ISDIR(lstatb.st_mode)
-#ifdef S_ISLNK
- && (!S_ISLNK(lstatb.st_mode)
- || stat_check() < 0
- || !S_ISDIR(statb.st_mode))
-#endif /* S_ISLNK */
- )
- return;
- /* Possibly tack on a trailing / if there isn't already
- * one and if the file is a directory or a symlink to a
- * directory
- */
- if (((check & GF_MARKDIR) && (check & GF_GLOBBED))
- && xp > Xstring(*xs, xp) && !ISDIRSEP(xp[-1])
- && (S_ISDIR(lstatb.st_mode)
-#ifdef S_ISLNK
- || (S_ISLNK(lstatb.st_mode)
- && stat_check() > 0
- && S_ISDIR(statb.st_mode))
-#endif /* S_ISLNK */
- ))
- {
- *xp++ = DIRSEP;
- *xp = '\0';
- }
- }
-#ifdef OS2 /* Done this way to avoid bug in gcc 2.7.2... */
- /* Ugly kludge required for command
- * completion - see how search_access()
- * is implemented for OS/2...
- */
-# define KLUDGE_VAL 4
-#else /* OS2 */
-# define KLUDGE_VAL 0
-#endif /* OS2 */
- XPput(*wp, str_nsave(Xstring(*xs, xp), Xlength(*xs, xp)
- + KLUDGE_VAL, ATEMP));
- return;
- }
-
- if (xp > Xstring(*xs, xp))
- *xp++ = DIRSEP;
- while (ISDIRSEP(*sp)) {
- Xcheck(*xs, xp);
- *xp++ = *sp++;
- }
- np = ksh_strchr_dirsep(sp);
- if (np != NULL) {
- se = np;
- odirsep = *np; /* don't assume DIRSEP, can be multiple kinds */
- *np++ = '\0';
- } else {
- odirsep = '\0'; /* keep gcc quiet */
- se = sp + strlen(sp);
- }
-
-
- /* Check if sp needs globbing - done to avoid pattern checks for strings
- * containing MAGIC characters, open ['s without the matching close ],
- * etc. (otherwise opendir() will be called which may fail because the
- * directory isn't readable - if no globbing is needed, only execute
- * permission should be required (as per POSIX)).
- */
- if (!has_globbing(sp, se)) {
- XcheckN(*xs, xp, se - sp + 1);
- debunk(xp, sp);
- xp += strlen(xp);
- *xpp = xp;
- globit(xs, xpp, np, wp, check);
- } else {
- DIR *dirp;
- struct dirent *d;
- char *name;
- int len;
- int prefix_len;
-
- /* xp = *xpp; copy_non_glob() may have re-alloc'd xs */
- *xp = '\0';
- prefix_len = Xlength(*xs, xp);
- dirp = ksh_opendir(prefix_len ? Xstring(*xs, xp) : ".");
- if (dirp == NULL)
- goto Nodir;
- while ((d = readdir(dirp)) != NULL) {
- name = d->d_name;
- if (name[0] == '.' &&
- (name[1] == 0 || (name[1] == '.' && name[2] == 0)))
- continue; /* always ignore . and .. */
- if ((*name == '.' && *sp != '.')
- || !gmatch(name, sp, TRUE))
- continue;
-
- len = NLENGTH(d) + 1;
- XcheckN(*xs, xp, len);
- memcpy(xp, name, len);
- *xpp = xp + len - 1;
- globit(xs, xpp, np, wp,
- (check & GF_MARKDIR) | GF_GLOBBED
- | (np ? GF_EXCHECK : GF_NONE));
- xp = Xstring(*xs, xp) + prefix_len;
- }
- closedir(dirp);
- Nodir:;
- }
-
- if (np != NULL)
- *--np = odirsep;
-}
-
-#if 0
-/* Check if p contains something that needs globbing; if it does, 0 is
- * returned; if not, p is copied into xs/xp after stripping any MAGICs
- */
-static int copy_non_glob ARGS((XString *xs, char **xpp, char *p));
-static int
-copy_non_glob(xs, xpp, p)
- XString *xs;
- char **xpp;
- char *p;
-{
- char *xp;
- int len = strlen(p);
-
- XcheckN(*xs, *xpp, len);
- xp = *xpp;
- for (; *p; p++) {
- if (ISMAGIC(*p)) {
- int c = *++p;
-
- if (c == '*' || c == '?')
- return 0;
- if (*p == '[') {
- char *q = p + 1;
-
- if (ISMAGIC(*q) && q[1] == NOT)
- q += 2;
- if (ISMAGIC(*q) && q[1] == ']')
- q += 2;
- for (; *q; q++)
- if (ISMAGIC(*q) && *++q == ']')
- return 0;
- /* pass a literal [ through */
- }
- /* must be a MAGIC-MAGIC, or MAGIC-!, MAGIC--, etc. */
- }
- *xp++ = *p;
- }
- *xp = '\0';
- *xpp = xp;
- return 1;
-}
-#endif /* 0 */
-
-/* remove MAGIC from string */
-char *
-debunk(dp, sp)
- char *dp;
- const char *sp;
-{
- char *d, *s;
-
- if ((s = strchr(sp, MAGIC))) {
- memcpy(dp, sp, s - sp);
- for (d = dp + (s - sp); *s; s++)
- if (!ISMAGIC(*s) || !(*++s & 0x80)
- || !strchr("*+?@!", *s & 0x7f))
- *d++ = *s;
- else {
- /* extended pattern operators: *+?@! */
- *d++ = *s & 0x7f;
- *d++ = '(';
- }
- *d = '\0';
- } else if (dp != sp)
- strcpy(dp, sp);
- return dp;
-}
-
-/* Check if p is an unquoted name, possibly followed by a / or :. If so
- * puts the expanded version in *dcp,dp and returns a pointer in p just
- * past the name, otherwise returns 0.
- */
-static char *
-maybe_expand_tilde(p, dsp, dpp, isassign)
- char *p;
- XString *dsp;
- char **dpp;
- int isassign;
-{
- XString ts;
- char *dp = *dpp;
- char *tp, *r;
-
- Xinit(ts, tp, 16, ATEMP);
- /* : only for DOASNTILDE form */
- while (p[0] == CHAR && !ISDIRSEP(p[1])
- && (!isassign || p[1] != PATHSEP))
- {
- Xcheck(ts, tp);
- *tp++ = p[1];
- p += 2;
- }
- *tp = '\0';
- r = (p[0] == EOS || p[0] == CHAR || p[0] == CSUBST) ? tilde(Xstring(ts, tp)) : (char *) 0;
- Xfree(ts, tp);
- if (r) {
- while (*r) {
- Xcheck(*dsp, dp);
- if (ISMAGIC(*r))
- *dp++ = MAGIC;
- *dp++ = *r++;
- }
- *dpp = dp;
- r = p;
- }
- return r;
-}
-
-/*
- * tilde expansion
- *
- * based on a version by Arnold Robbins
- */
-
-static char *
-tilde(cp)
- char *cp;
-{
- char *dp;
-
- if (cp[0] == '\0')
- dp = str_val(global("HOME"));
- else if (cp[0] == '+' && cp[1] == '\0')
- dp = str_val(global("PWD"));
- else if (cp[0] == '-' && cp[1] == '\0')
- dp = str_val(global("OLDPWD"));
- else
- dp = homedir(cp);
- /* If HOME, PWD or OLDPWD are not set, don't expand ~ */
- if (dp == null)
- dp = (char *) 0;
- return dp;
-}
-
-/*
- * map userid to user's home directory.
- * note that 4.3's getpw adds more than 6K to the shell,
- * and the YP version probably adds much more.
- * we might consider our own version of getpwnam() to keep the size down.
- */
-
-static char *
-homedir(name)
- char *name;
-{
- register struct tbl *ap;
-
- ap = tenter(&homedirs, name, hash(name));
- if (!(ap->flag & ISSET)) {
-#ifdef OS2
- /* No usernames in OS2 - punt */
- return NULL;
-#else /* OS2 */
- struct passwd *pw;
-
- pw = getpwnam(name);
- if (pw == NULL)
- return NULL;
- ap->val.s = str_save(pw->pw_dir, APERM);
- ap->flag |= DEFINED|ISSET|ALLOC;
-#endif /* OS2 */
- }
- return ap->val.s;
-}
-
-#ifdef BRACE_EXPAND
-static void
-alt_expand(wp, start, exp_start, end, fdo)
- XPtrV *wp;
- char *start, *exp_start;
- char *end;
- int fdo;
-{
- int UNINITIALIZED(count);
- char *brace_start, *brace_end, *UNINITIALIZED(comma);
- char *field_start;
- char *p;
-
- /* search for open brace */
- for (p = exp_start; (p = strchr(p, MAGIC)) && p[1] != OBRACE; p += 2)
- ;
- brace_start = p;
-
- /* find matching close brace, if any */
- if (p) {
- comma = (char *) 0;
- count = 1;
- for (p += 2; *p && count; p++) {
- if (ISMAGIC(*p)) {
- if (*++p == OBRACE)
- count++;
- else if (*p == CBRACE)
- --count;
- else if (*p == ',' && count == 1)
- comma = p;
- }
- }
- }
- /* no valid expansions... */
- if (!p || count != 0) {
- /* Note that given a{{b,c} we do not expand anything (this is
- * what at&t ksh does. This may be changed to do the {b,c}
- * expansion. }
- */
- if (fdo & DOGLOB)
- glob(start, wp, fdo & DOMARKDIRS);
- else
- XPput(*wp, debunk(start, start));
- return;
- }
- brace_end = p;
- if (!comma) {
- alt_expand(wp, start, brace_end, end, fdo);
- return;
- }
-
- /* expand expression */
- field_start = brace_start + 2;
- count = 1;
- for (p = brace_start + 2; p != brace_end; p++) {
- if (ISMAGIC(*p)) {
- if (*++p == OBRACE)
- count++;
- else if ((*p == CBRACE && --count == 0)
- || (*p == ',' && count == 1))
- {
- char *new;
- int l1, l2, l3;
-
- l1 = brace_start - start;
- l2 = (p - 1) - field_start;
- l3 = end - brace_end;
- new = (char *) alloc(l1 + l2 + l3 + 1, ATEMP);
- memcpy(new, start, l1);
- memcpy(new + l1, field_start, l2);
- memcpy(new + l1 + l2, brace_end, l3);
- new[l1 + l2 + l3] = '\0';
- alt_expand(wp, new, new + l1,
- new + l1 + l2 + l3, fdo);
- field_start = p + 1;
- }
- }
- }
- return;
-}
-#endif /* BRACE_EXPAND */
diff --git a/bin/pdksh/exec.c b/bin/pdksh/exec.c
deleted file mode 100644
index 7c98d956239..00000000000
--- a/bin/pdksh/exec.c
+++ /dev/null
@@ -1,1671 +0,0 @@
-/* $OpenBSD: exec.c,v 1.10 1997/09/12 04:38:05 millert Exp $ */
-
-/*
- * execute command tree
- */
-
-#include "sh.h"
-#include "c_test.h"
-#include <ctype.h>
-#include "ksh_stat.h"
-
-/* Does ps4 get parameter substitutions done? */
-#ifdef KSH
-# define PS4_SUBSTITUTE(s) substitute((s), 0)
-#else
-# define PS4_SUBSTITUTE(s) (s)
-#endif /* KSH */
-
-static int comexec ARGS((struct op *t, struct tbl *volatile tp, char **ap,
- int volatile flags));
-static void scriptexec ARGS((struct op *tp, char **ap));
-static int call_builtin ARGS((struct tbl *tp, char **wp));
-static int iosetup ARGS((struct ioword *iop, struct tbl *tp));
-static int herein ARGS((char *hname, int sub));
-#ifdef KSH
-static char *do_selectargs ARGS((char **ap, bool_t print_menu));
-#endif /* KSH */
-#ifdef KSH
-static int dbteste_isa ARGS((Test_env *te, Test_meta meta));
-static const char *dbteste_getopnd ARGS((Test_env *te, Test_op op,
- int do_eval));
-static int dbteste_eval ARGS((Test_env *te, Test_op op, const char *opnd1,
- const char *opnd2, int do_eval));
-static void dbteste_error ARGS((Test_env *te, int offset, const char *msg));
-#endif /* KSH */
-#ifdef OS2
-static int search_access1 ARGS((const char *path, int mode, int *errnop));
-#endif /* OS2 */
-
-
-/*
- * handle systems that don't have F_SETFD
- */
-#ifndef F_SETFD
-# ifndef MAXFD
-# define MAXFD 64
-# endif
-/* a bit field would be smaller, but this will work */
-static char clexec_tab[MAXFD+1];
-#endif
-
-/*
- * we now use this function always.
- */
-int
-fd_clexec(fd)
- int fd;
-{
-#ifndef F_SETFD
- if (fd >= 0 && fd < sizeof(clexec_tab)) {
- clexec_tab[fd] = 1;
- return 0;
- }
- return -1;
-#else
- return fcntl(fd, F_SETFD, 1);
-#endif
-}
-
-
-/*
- * execute command tree
- */
-int
-execute(t, flags)
- struct op * volatile t;
- volatile int flags; /* if XEXEC don't fork */
-{
- int i;
- volatile int rv = 0;
- int pv[2];
- char ** volatile ap;
- char *s, *cp;
- struct ioword **iowp;
- struct tbl *tp = NULL;
-
- if (t == NULL)
- return 0;
-
- /* Is this the end of a pipeline? If so, we want to evaluate the
- * command arguments
- bool_t eval_done = FALSE;
- if ((flags&XFORK) && !(flags&XEXEC) && (flags&XPCLOSE)) {
- eval_done = TRUE;
- tp = eval_execute_args(t, &ap);
- }
- */
- if ((flags&XFORK) && !(flags&XEXEC) && t->type != TPIPE)
- return exchild(t, flags, -1); /* run in sub-process */
-
- newenv(E_EXEC);
- if (trap)
- runtraps(0);
-
- if (t->type == TCOM) {
- /* Clear subst_exstat before argument expansion. Used by
- * null commands (see comexec()) and by c_set().
- */
- subst_exstat = 0;
-
- /* POSIX says expand command words first, then redirections,
- * and assignments last..
- */
- ap = eval(t->args, t->u.evalflags | DOBLANK | DOGLOB | DOTILDE);
- if (Flag(FXTRACE) && ap[0]) {
- shf_fprintf(shl_out, "%s",
- PS4_SUBSTITUTE(str_val(global("PS4"))));
- for (i = 0; ap[i]; i++)
- shf_fprintf(shl_out, "%s%s", ap[i],
- ap[i + 1] ? space : newline);
- shf_flush(shl_out);
- }
- if (ap[0])
- tp = findcom(ap[0], FC_BI|FC_FUNC);
- }
-
- if (t->ioact != NULL || t->type == TPIPE || t->type == TCOPROC) {
- e->savefd = (short *) alloc(sizeofN(short, NUFILE), ATEMP);
- /* initialize to not redirected */
- memset(e->savefd, 0, sizeofN(short, NUFILE));
- }
-
- /* do redirection, to be restored in quitenv() */
- if (t->ioact != NULL)
- for (iowp = t->ioact; *iowp != NULL; iowp++) {
- if (iosetup(*iowp, tp) < 0) {
- exstat = rv = 1;
- /* Redirection failures for special commands
- * cause (non-interactive) shell to exit.
- */
- if (tp && tp->type == CSHELL
- && (tp->flag & SPEC_BI))
- errorf(null);
- /* Deal with FERREXIT, quitenv(), etc. */
- goto Break;
- }
- }
-
- switch(t->type) {
- case TCOM:
- rv = comexec(t, tp, ap, flags);
- break;
-
- case TPAREN:
- rv = execute(t->left, flags|XFORK);
- break;
-
- case TPIPE:
- flags |= XFORK;
- flags &= ~XEXEC;
- e->savefd[0] = savefd(0, 0);
- (void) ksh_dup2(e->savefd[0], 0, FALSE); /* stdin of first */
- e->savefd[1] = savefd(1, 0);
- while (t->type == TPIPE) {
- openpipe(pv);
- (void) ksh_dup2(pv[1], 1, FALSE); /* stdout of curr */
- /* Let exchild() close pv[0] in child
- * (if this isn't done, commands like
- * (: ; cat /etc/termcap) | sleep 1
- * will hang forever).
- */
- exchild(t->left, flags|XPIPEO|XCCLOSE, pv[0]);
- (void) ksh_dup2(pv[0], 0, FALSE); /* stdin of next */
- closepipe(pv);
- flags |= XPIPEI;
- t = t->right;
- }
- restfd(1, e->savefd[1]); /* stdout of last */
- e->savefd[1] = 0; /* no need to re-restore this */
- /* Let exchild() close 0 in parent, after fork, before wait */
- i = exchild(t, flags|XPCLOSE, 0);
- if (!(flags&XBGND) && !(flags&XXCOM))
- rv = i;
- break;
-
- case TLIST:
- while (t->type == TLIST) {
- execute(t->left, flags & XERROK);
- t = t->right;
- }
- rv = execute(t, flags & XERROK);
- break;
-
-#ifdef KSH
- case TCOPROC:
- {
-# ifdef JOB_SIGS
- sigset_t omask;
-# endif /* JOB_SIGS */
-
-# ifdef JOB_SIGS
- /* Block sigchild as we are using things changed in the
- * signal handler
- */
- sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
- e->type = E_ERRH;
- i = ksh_sigsetjmp(e->jbuf, 0);
- if (i) {
- sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0);
- quitenv();
- unwind(i);
- /*NOTREACHED*/
- }
-# endif /* JOB_SIGS */
- /* Already have a (live) co-process? */
- if (coproc.job && coproc.write >= 0)
- errorf("coprocess already exists");
-
- /* Can we re-use the existing co-process pipe? */
- coproc_cleanup(TRUE);
-
- /* do this before opening pipes, in case these fail */
- e->savefd[0] = savefd(0, 0);
- e->savefd[1] = savefd(1, 0);
-
- openpipe(pv);
- ksh_dup2(pv[0], 0, FALSE);
- close(pv[0]);
- coproc.write = pv[1];
- coproc.job = (void *) 0;
-
- if (coproc.readw >= 0)
- ksh_dup2(coproc.readw, 1, FALSE);
- else {
- openpipe(pv);
- coproc.read = pv[0];
- ksh_dup2(pv[1], 1, FALSE);
- coproc.readw = pv[1]; /* closed before first read */
- coproc.njobs = 0;
- /* create new coprocess id */
- ++coproc.id;
- }
-# ifdef JOB_SIGS
- sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0);
- e->type = E_EXEC; /* no more need for error handler */
-# endif /* JOB_SIGS */
-
- /* exchild() closes coproc.* in child after fork,
- * will also increment coproc.njobs when the
- * job is actually created.
- */
- flags &= ~XEXEC;
- exchild(t->left, flags|XBGND|XFORK|XCOPROC|XCCLOSE,
- coproc.readw);
- break;
- }
-#endif /* KSH */
-
- case TASYNC:
- /* XXX non-optimal, I think - "(foo &)", forks for (),
- * forks again for async... parent should optimize
- * this to "foo &"...
- */
- rv = execute(t->left, (flags&~XEXEC)|XBGND|XFORK);
- break;
-
- case TOR:
- case TAND:
- rv = execute(t->left, XERROK);
- if (t->right != NULL && (rv == 0) == (t->type == TAND))
- rv = execute(t->right, flags & XERROK);
- else
- flags |= XERROK;
- break;
-
- case TBANG:
- rv = !execute(t->right, XERROK);
- break;
-
-#ifdef KSH
- case TDBRACKET:
- {
- Test_env te;
-
- te.flags = TEF_DBRACKET;
- te.pos.wp = t->args;
- te.isa = dbteste_isa;
- te.getopnd = dbteste_getopnd;
- te.eval = dbteste_eval;
- te.error = dbteste_error;
-
- rv = test_parse(&te);
- break;
- }
-#endif /* KSH */
-
- case TFOR:
-#ifdef KSH
- case TSELECT:
- {
- volatile bool_t is_first = TRUE;
-#endif /* KSH */
- ap = (t->vars != NULL) ?
- eval(t->vars, DOBLANK|DOGLOB|DOTILDE)
- : e->loc->argv + 1;
- e->type = E_LOOP;
- while (1) {
- i = ksh_sigsetjmp(e->jbuf, 0);
- if (!i)
- break;
- if ((e->flags&EF_BRKCONT_PASS)
- || (i != LBREAK && i != LCONTIN))
- {
- quitenv();
- unwind(i);
- } else if (i == LBREAK) {
- rv = 0;
- goto Break;
- }
- }
- rv = 0; /* in case of a continue */
- if (t->type == TFOR) {
- struct tbl *vq;
-
- while (*ap != NULL) {
- vq = global(t->str);
- if (vq->flag & RDONLY)
- errorf("%s is read only", t->str);
- setstr(vq, *ap++);
- rv = execute(t->left, flags & XERROK);
- }
- }
-#ifdef KSH
- else { /* TSELECT */
- struct tbl *vq;
-
- for (;;) {
- if (!(cp = do_selectargs(ap, is_first))) {
- rv = 1;
- break;
- }
- is_first = FALSE;
- vq = global(t->str);
- if (vq->flag & RDONLY)
- errorf("%s is read only", t->str);
- setstr(vq, cp);
- rv = execute(t->left, flags & XERROK);
- }
- }
- }
-#endif /* KSH */
- break;
-
- case TWHILE:
- case TUNTIL:
- e->type = E_LOOP;
- while (1) {
- i = ksh_sigsetjmp(e->jbuf, 0);
- if (!i)
- break;
- if ((e->flags&EF_BRKCONT_PASS)
- || (i != LBREAK && i != LCONTIN))
- {
- quitenv();
- unwind(i);
- } else if (i == LBREAK) {
- rv = 0;
- goto Break;
- }
- }
- rv = 0; /* in case of a continue */
- while ((execute(t->left, XERROK) == 0) == (t->type == TWHILE))
- rv = execute(t->right, flags & XERROK);
- break;
-
- case TIF:
- case TELIF:
- if (t->right == NULL)
- break; /* should be error */
- rv = execute(t->left, XERROK) == 0 ?
- execute(t->right->left, flags & XERROK) :
- execute(t->right->right, flags & XERROK);
- break;
-
- case TCASE:
- cp = evalstr(t->str, DOTILDE);
- for (t = t->left; t != NULL && t->type == TPAT; t = t->right)
- for (ap = t->vars; *ap; ap++)
- if ((s = evalstr(*ap, DOTILDE|DOPAT))
- && gmatch(cp, s, FALSE))
- goto Found;
- break;
- Found:
- rv = execute(t->left, flags & XERROK);
- break;
-
- case TBRACE:
- rv = execute(t->left, flags & XERROK);
- break;
-
- case TFUNCT:
- rv = define(t->str, t);
- break;
-
- case TTIME:
- rv = timex(t, flags);
- break;
-
- case TEXEC: /* an eval'd TCOM */
- s = t->args[0];
- ap = makenv();
-#ifndef F_SETFD
- for (i = 0; i < sizeof(clexec_tab); i++)
- if (clexec_tab[i]) {
- close(i);
- clexec_tab[i] = 0;
- }
-#endif
- restoresigs();
- cleanup_proc_env();
- ksh_execve(t->str, t->args, ap);
- if (errno == ENOEXEC)
- scriptexec(t, ap);
- else
- errorf("%s: %s", s, strerror(errno));
- }
- Break:
- exstat = rv;
-
- quitenv(); /* restores IO */
- if ((flags&XEXEC))
- exit(rv); /* exit child */
- if (rv != 0 && !(flags & XERROK)) {
- if (Flag(FERREXIT))
- unwind(LERROR);
- trapsig(SIGERR_);
- }
- return rv;
-}
-
-/*
- * execute simple command
- */
-
-static int
-comexec(t, tp, ap, flags)
- struct op *t;
- struct tbl *volatile tp;
- register char **ap;
- int volatile flags;
-{
- int i;
- int rv = 0;
- register char *cp;
- register char **lastp;
- static struct op texec; /* Must be static (XXX but why?) */
- int type_flags;
- int keepasn_ok;
- int fcflags = FC_BI|FC_FUNC|FC_PATH;
-
-#ifdef __GNUC__
- (void)&rv;
-#endif
-
- /* snag the last argument for $_ XXX not the same as at&t ksh,
- * which only seems to set $_ after a newline (but not in
- * functions/dot scripts, but in interactive and scipt) -
- * perhaps save last arg here and set it in shell()?.
- */
- if (!Flag(FSH) && *(lastp = ap)) {
- while (*++lastp)
- ;
- setstr(typeset("_", LOCAL, 0, 0, 0), *--lastp);
- }
-
- /* Deal with the shell builtins builtin, exec and command since
- * they can be followed by other commands. This must be done before
- * we know if we should create a local block, which must be done
- * before we can do a path search (in case the assignments change
- * PATH).
- * Odd cases:
- * FOO=bar exec > /dev/null FOO is kept but not exported
- * FOO=bar exec foobar FOO is exported
- * FOO=bar command exec > /dev/null FOO is neither kept nor exported
- * FOO=bar command FOO is neither kept nor exported
- * PATH=... foobar use new PATH in foobar search
- */
- keepasn_ok = 1;
- while (tp && tp->type == CSHELL) {
- fcflags = FC_BI|FC_FUNC|FC_PATH;/* undo effects of command */
- if (tp->val.f == c_builtin) {
- if ((cp = *++ap) == NULL) {
- tp = NULL;
- break;
- }
- tp = findcom(cp, FC_BI);
- if (tp == NULL)
- errorf("builtin: %s: not a builtin", cp);
- continue;
- } else if (tp->val.f == c_exec) {
- if (ap[1] == NULL)
- break;
- ap++;
- flags |= XEXEC;
- } else if (tp->val.f == c_command) {
- int optc, saw_p = 0;
-
- /* Ugly dealing with options in two places (here and
- * in c_command(), but such is life)
- */
- ksh_getopt_reset(&builtin_opt, 0);
- while ((optc = ksh_getopt(ap, &builtin_opt, ":p"))
- == 'p')
- saw_p = 1;
- if (optc != EOF)
- break; /* command -vV or something */
- /* don't look for functions */
- fcflags = FC_BI|FC_PATH;
- if (saw_p) {
- if (Flag(FRESTRICTED)) {
- warningf(TRUE,
- "command -p: restricted");
- rv = 1;
- goto Leave;
- }
- fcflags |= FC_DEFPATH;
- }
- ap += builtin_opt.optind;
- /* POSIX says special builtins lose their status
- * if accessed using command.
- */
- keepasn_ok = 0;
- if (!ap[0]) {
- /* ensure command with no args exits with 0 */
- subst_exstat = 0;
- break;
- }
- } else
- break;
- tp = findcom(ap[0], fcflags & (FC_BI|FC_FUNC));
- }
- if (keepasn_ok && (!ap[0] || (tp && (tp->flag & KEEPASN))))
- type_flags = 0;
- else {
- /* create new variable/function block */
- newblock();
- /* ksh functions don't keep assignments, POSIX functions do. */
- if (keepasn_ok && tp && tp->type == CFUNC
- && !(tp->flag & FKSH))
- type_flags = 0;
- else
- type_flags = LOCAL|LOCAL_COPY|EXPORT;
- }
- if (Flag(FEXPORT))
- type_flags |= EXPORT;
- for (i = 0; t->vars[i]; i++) {
- cp = evalstr(t->vars[i], DOASNTILDE);
- if (Flag(FXTRACE)) {
- if (i == 0)
- shf_fprintf(shl_out, "%s",
- PS4_SUBSTITUTE(str_val(global("PS4"))));
- shf_fprintf(shl_out, "%s%s", cp,
- t->vars[i + 1] ? space : newline);
- if (!t->vars[i + 1])
- shf_flush(shl_out);
- }
- typeset(cp, type_flags, 0, 0, 0);
- }
-
- if ((cp = *ap) == NULL) {
- rv = subst_exstat;
- goto Leave;
- } else if (!tp) {
- if (Flag(FRESTRICTED) && ksh_strchr_dirsep(cp)) {
- warningf(TRUE, "%s: restricted", cp);
- rv = 1;
- goto Leave;
- }
- tp = findcom(cp, fcflags);
- }
-
- switch (tp->type) {
- case CSHELL: /* shell built-in */
- rv = call_builtin(tp, ap);
- break;
-
- case CFUNC: /* function call */
- {
- volatile int old_xflag;
- volatile Tflag old_inuse;
- const char *volatile old_kshname;
-
- if (!(tp->flag & ISSET)) {
- struct tbl *ftp;
-
- if (!tp->u.fpath) {
- if (tp->u2.errno_) {
- warningf(TRUE,
- "%s: can't find function definition file - %s",
- cp, strerror(tp->u2.errno_));
- rv = 126;
- } else {
- warningf(TRUE,
- "%s: can't find function definition file", cp);
- rv = 127;
- }
- break;
- }
- if (include(tp->u.fpath, 0, (char **) 0, 0) < 0) {
- warningf(TRUE,
- "%s: can't open function definition file %s - %s",
- cp, tp->u.fpath, strerror(errno));
- rv = 127;
- break;
- }
- if (!(ftp = findfunc(cp, hash(cp), FALSE))
- || !(ftp->flag & ISSET))
- {
- warningf(TRUE,
- "%s: function not defined by %s",
- cp, tp->u.fpath);
- rv = 127;
- break;
- }
- tp = ftp;
- }
-
- /* ksh functions set $0 to function name, POSIX functions leave
- * $0 unchanged.
- */
- old_kshname = kshname;
- if (tp->flag & FKSH)
- kshname = ap[0];
- e->loc->argv = ap;
- for (i = 0; *ap++ != NULL; i++)
- ;
- e->loc->argc = i - 1;
- getopts_reset(1);
-
- old_xflag = Flag(FXTRACE);
- Flag(FXTRACE) = tp->flag & TRACE ? TRUE : FALSE;
-
- old_inuse = tp->flag & FINUSE;
- tp->flag |= FINUSE;
-
- e->type = E_FUNC;
- i = ksh_sigsetjmp(e->jbuf, 0);
- if (i == 0) {
- /* seems odd to pass XERROK here, but at&t ksh does */
- exstat = execute(tp->val.t, flags & XERROK);
- i = LRETURN;
- }
- kshname = old_kshname;
- Flag(FXTRACE) = old_xflag;
- tp->flag = (tp->flag & ~FINUSE) | old_inuse;
- /* Were we deleted while executing? If so, free the execution
- * tree. todo: Unfortunately, the table entry is never re-used
- * until the lookup table is expanded.
- */
- if ((tp->flag & (FDELETE|FINUSE)) == FDELETE) {
- if (tp->flag & ALLOC) {
- tp->flag &= ~ALLOC;
- tfree(tp->val.t, tp->areap);
- }
- tp->flag = 0;
- }
- switch (i) {
- case LRETURN:
- case LERROR:
- rv = exstat;
- break;
- case LINTR:
- case LEXIT:
- case LLEAVE:
- case LSHELL:
- quitenv();
- unwind(i);
- /*NOTREACHED*/
- default:
- quitenv();
- internal_errorf(1, "CFUNC %d", i);
- }
- break;
- }
-
- case CEXEC: /* executable command */
- case CTALIAS: /* tracked alias */
- if (!(tp->flag&ISSET)) {
- /* errno_ will be set if the named command was found
- * but could not be executed (permissions, no execute
- * bit, directory, etc). Print out a (hopefully)
- * useful error message and set the exit status to 126.
- */
- if (tp->u2.errno_) {
- warningf(TRUE, "%s: cannot execute - %s", cp,
- strerror(tp->u2.errno_));
- rv = 126; /* POSIX */
- } else {
- warningf(TRUE, "%s: not found", cp);
- rv = 127;
- }
- break;
- }
-
- if (!Flag(FSH)) {
- /* set $_ to program's full path */
- setstr(typeset("_", LOCAL|EXPORT, 0, 0, 0), tp->val.s);
- }
-
- if (flags&XEXEC) {
- j_exit();
- if (!(flags&XBGND) || Flag(FMONITOR)) {
- setexecsig(&sigtraps[SIGINT], SS_RESTORE_ORIG);
- setexecsig(&sigtraps[SIGQUIT], SS_RESTORE_ORIG);
- }
- }
-
- /* to fork we set up a TEXEC node and call execute */
- texec.type = TEXEC;
- texec.left = t; /* for tprint */
- texec.str = tp->val.s;
- texec.args = ap;
- rv = exchild(&texec, flags, -1);
- break;
- }
- Leave:
- if (flags & XEXEC) {
- exstat = rv;
- unwind(LLEAVE);
- }
- return rv;
-}
-
-static void
-scriptexec(tp, ap)
- register struct op *tp;
- register char **ap;
-{
- char *shell;
-
- shell = str_val(global(EXECSHELL_STR));
- if (shell && *shell)
- shell = search(shell, path, X_OK, (int *) 0);
- if (!shell || !*shell)
- shell = EXECSHELL;
-
- *tp->args-- = tp->str;
-#ifdef SHARPBANG
- {
- char buf[LINE];
- register char *cp;
- register int fd, n;
-
- buf[0] = '\0';
- if ((fd = open(tp->str, O_RDONLY)) >= 0) {
- if ((n = read(fd, buf, LINE - 1)) > 0)
- buf[n] = '\0';
- (void) close(fd);
- }
- if ((buf[0] == '#' && buf[1] == '!' && (cp = &buf[2]))
-# ifdef OS2
- || (strncmp(buf, "extproc", 7) == 0 && isspace(buf[7])
- && (cp = &buf[7]))
-# endif /* OS2 */
- )
- {
- while (*cp && (*cp == ' ' || *cp == '\t'))
- cp++;
- if (*cp && *cp != '\n') {
- char *a0 = cp, *a1 = (char *) 0;
-# ifdef OS2
- char *a2 = cp;
-# endif /* OS2 */
-
- while (*cp && *cp != '\n' && *cp != ' '
- && *cp != '\t')
- {
-# ifdef OS2
- /* Allow shell search without prepended path
- * if shell with / in pathname cannot be found.
- * Use / explicitly so \ can be used if explicit
- * needs to be forced.
- */
- if (*cp == '/')
- a2 = cp + 1;
-# endif /* OS2 */
- cp++;
- }
- if (*cp && *cp != '\n') {
- *cp++ = '\0';
- while (*cp
- && (*cp == ' ' || *cp == '\t'))
- cp++;
- if (*cp && *cp != '\n') {
- a1 = cp;
- /* all one argument */
- while (*cp && *cp != '\n')
- cp++;
- }
- }
- if (*cp == '\n') {
- *cp = '\0';
- if (a1)
- *tp->args-- = a1;
-# ifdef OS2
- if (a0 != a2 && search_access(a0, X_OK, (int *) 0))
- a0 = a2;
-# endif /* OS2 */
- shell = a0;
- }
- }
-# ifdef OS2
- } else {
- /* Use ksh documented shell default if present
- * else use OS2_SHELL which is assumed to need
- * the /c option and '\' as dir separater.
- */
- char *p = shell;
-
- shell = str_val(global("EXECSHELL"));
- if (shell && *shell)
- shell = search(shell, path, X_OK, (int *) 0);
- if (!shell || !*shell) {
- shell = p;
- *tp->args-- = "/c";
- for (p = tp->str; *p; p++)
- if (*p == '/')
- *p = '\\';
- }
-# endif /* OS2 */
- }
- }
-#endif /* SHARPBANG */
- *tp->args = shell;
-
- ksh_execve(tp->args[0], tp->args, ap);
-
- /* report both the program that was run and the bogus shell */
- errorf("%s: %s: %s", tp->str, shell, strerror(errno));
-}
-
-int
-shcomexec(wp)
- register char **wp;
-{
- register struct tbl *tp;
-
- tp = tsearch(&builtins, *wp, hash(*wp));
- if (tp == NULL)
- internal_errorf(1, "shcomexec: %s", *wp);
- return call_builtin(tp, wp);
-}
-
-/*
- * Search function tables for a function. If create set, a table entry
- * is created if none is found.
- */
-struct tbl *
-findfunc(name, h, create)
- const char *name;
- unsigned int h;
- int create;
-{
- struct block *l;
- struct tbl *tp = (struct tbl *) 0;
-
- for (l = e->loc; l; l = l->next) {
- tp = tsearch(&l->funs, name, h);
- if (tp)
- break;
- if (!l->next && create) {
- tp = tenter(&l->funs, name, h);
- tp->flag = DEFINED;
- tp->type = CFUNC;
- tp->val.t = (struct op *) 0;
- break;
- }
- }
- return tp;
-}
-
-/*
- * define function. Returns 1 if function is being undefined (t == 0) and
- * function did not exist, returns 0 otherwise.
- */
-int
-define(name, t)
- const char *name;
- struct op *t;
-{
- struct tbl *tp;
- int was_set = 0;
-
- while (1) {
- tp = findfunc(name, hash(name), TRUE);
-
- if (tp->flag & ISSET)
- was_set = 1;
- /* If this function is currently being executed, we zap this
- * table entry so findfunc() won't see it
- */
- if (tp->flag & FINUSE) {
- tp->name[0] = '\0';
- tp->flag &= ~DEFINED; /* ensure it won't be found */
- tp->flag |= FDELETE;
- } else
- break;
- }
-
- if (tp->flag & ALLOC) {
- tp->flag &= ~(ISSET|ALLOC);
- tfree(tp->val.t, tp->areap);
- }
-
- if (t == NULL) { /* undefine */
- tdelete(tp);
- return was_set ? 0 : 1;
- }
-
- tp->val.t = tcopy(t->left, tp->areap);
- tp->flag |= (ISSET|ALLOC);
- if (t->u.ksh_func)
- tp->flag |= FKSH;
-
- return 0;
-}
-
-/*
- * add builtin
- */
-void
-builtin(name, func)
- const char *name;
- int (*func) ARGS((char **));
-{
- register struct tbl *tp;
- Tflag flag;
-
- /* see if any flags should be set for this builtin */
- for (flag = 0; ; name++) {
- if (*name == '=') /* command does variable assignment */
- flag |= KEEPASN;
- else if (*name == '*') /* POSIX special builtin */
- flag |= SPEC_BI;
- else if (*name == '+') /* POSIX regular builtin */
- flag |= REG_BI;
- else
- break;
- }
-
- tp = tenter(&builtins, name, hash(name));
- tp->flag = DEFINED | flag;
- tp->type = CSHELL;
- tp->val.f = func;
-}
-
-/*
- * find command
- * either function, hashed command, or built-in (in that order)
- */
-struct tbl *
-findcom(name, flags)
- const char *name;
- int flags; /* FC_* */
-{
- static struct tbl temp;
- unsigned int h = hash(name);
- struct tbl *tp = NULL, *tbi;
- int insert = Flag(FTRACKALL); /* insert if not found */
- char *fpath; /* for function autoloading */
- char *npath;
-
- if (ksh_strchr_dirsep(name) != NULL) {
- insert = 0;
- /* prevent FPATH search below */
- flags &= ~FC_FUNC;
- goto Search;
- }
- tbi = (flags & FC_BI) ? tsearch(&builtins, name, h) : NULL;
- /* POSIX says special builtins first, then functions, then
- * POSIX regular builtins, then search path...
- */
- if ((flags & FC_SPECBI) && tbi && (tbi->flag & SPEC_BI))
- tp = tbi;
- if (!tp && (flags & FC_FUNC)) {
- tp = findfunc(name, h, FALSE);
- if (tp && !(tp->flag & ISSET)) {
- if ((fpath = str_val(global("FPATH"))) == null) {
- tp->u.fpath = (char *) 0;
- tp->u2.errno_ = 0;
- } else
- tp->u.fpath = search(name, fpath, R_OK,
- &tp->u2.errno_);
- }
- }
- if (!tp && (flags & FC_REGBI) && tbi && (tbi->flag & REG_BI))
- tp = tbi;
- /* todo: posix says non-special/non-regular builtins must
- * be triggered by some user-controllable means like a
- * special directory in PATH. Requires modifications to
- * the search() function. Tracked aliases should be
- * modified to allow tracking of builtin commands.
- * This should be under control of the FPOSIX flag.
- * If this is changed, also change c_whence...
- */
- if (!tp && (flags & FC_UNREGBI) && tbi)
- tp = tbi;
- if (!tp && (flags & FC_PATH) && !(flags & FC_DEFPATH)) {
- tp = tsearch(&taliases, name, h);
- if (tp && (tp->flag & ISSET) && eaccess(tp->val.s, X_OK) != 0) {
- if (tp->flag & ALLOC) {
- tp->flag &= ~ALLOC;
- afree(tp->val.s, APERM);
- }
- tp->flag &= ~ISSET;
- }
- }
-
- Search:
- if ((!tp || (tp->type == CTALIAS && !(tp->flag&ISSET)))
- && (flags & FC_PATH))
- {
- if (!tp) {
- if (insert && !(flags & FC_DEFPATH)) {
- tp = tenter(&taliases, name, h);
- tp->type = CTALIAS;
- } else {
- tp = &temp;
- tp->type = CEXEC;
- }
- tp->flag = DEFINED; /* make ~ISSET */
- }
- npath = search(name, flags & FC_DEFPATH ? def_path : path,
- X_OK, &tp->u2.errno_);
- if (npath) {
- tp->val.s = tp == &temp ? npath : str_save(npath, APERM);
- tp->flag |= ISSET|ALLOC;
- } else if ((flags & FC_FUNC)
- && (fpath = str_val(global("FPATH"))) != null
- && (npath = search(name, fpath, R_OK,
- &tp->u2.errno_)) != (char *) 0)
- {
- /* An undocumented feature of at&t ksh is that it
- * searches FPATH if a command is not found, even
- * if the command hasn't been set up as an autoloaded
- * function (ie, no typeset -uf).
- */
- tp = &temp;
- tp->type = CFUNC;
- tp->flag = DEFINED; /* make ~ISSET */
- tp->u.fpath = npath;
- }
- }
- return tp;
-}
-
-/*
- * flush executable commands with relative paths
- */
-void
-flushcom(all)
- int all; /* just relative or all */
-{
- struct tbl *tp;
- struct tstate ts;
-
- for (twalk(&ts, &taliases); (tp = tnext(&ts)) != NULL; )
- if ((tp->flag&ISSET) && (all || !ISDIRSEP(tp->val.s[0]))) {
- if (tp->flag&ALLOC) {
- tp->flag &= ~(ALLOC|ISSET);
- afree(tp->val.s, APERM);
- }
- tp->flag = ~ISSET;
- }
-}
-
-/* Check if path is something we want to find. Returns -1 for failure. */
-int
-search_access(path, mode, errnop)
- const char *path;
- int mode;
- int *errnop; /* set if candidate found, but not suitable */
-{
-#ifndef OS2
- int ret, err = 0;
- struct stat statb;
-
- if (stat(path, &statb) < 0)
- return -1;
- ret = eaccess(path, mode);
- if (ret < 0)
- err = errno; /* File exists, but we can't access it */
- else if (mode == X_OK && (!S_ISREG(statb.st_mode)
- /* This 'cause access() says root can execute everything */
- || !(statb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH))))
- {
- ret = -1;
- err = S_ISDIR(statb.st_mode) ? EISDIR : EACCES;
- }
- if (err && errnop)
- *errnop = err;
- return ret;
-#else /* !OS2 */
- /*
- * NOTE: ASSUMES path can be modified and has enough room at the
- * end of the string for a suffix (ie, 4 extra characters).
- * Certain code knows this (eg, eval.c(globit()),
- * exec.c(search())).
- */
- static char *xsuffixes[] = { ".ksh", ".exe", ".", ".sh", ".cmd",
- ".com", ".bat", (char *) 0
- };
- static char *rsuffixes[] = { ".ksh", ".", ".sh", ".cmd", ".bat",
- (char *) 0
- };
- int i;
- char *mpath = (char *) path;
- char *tp = mpath + strlen(mpath);
- char *p;
- char **sfx;
-
- /* If a suffix has been specified, check if it is one of the
- * suffixes that indicate the file is executable - if so, change
- * the access test to R_OK...
- * This code assumes OS/2 files can have only one suffix...
- */
- if ((p = strrchr((p = ksh_strrchr_dirsep(mpath)) ? p : mpath, '.'))) {
- if (mode == X_OK)
- mode = R_OK;
- return search_access1(mpath, mode, errnop);
- }
- /* Try appending the various suffixes. Different suffixes for
- * read and execute 'cause we don't want to read an executable...
- */
- sfx = mode == R_OK ? rsuffixes : xsuffixes;
- for (i = 0; sfx[i]; i++) {
- strcpy(tp, p = sfx[i]);
- if (search_access1(mpath, R_OK, errnop) == 0)
- return 0;
- *tp = '\0';
- }
- return -1;
-#endif /* !OS2 */
-}
-
-#ifdef OS2
-static int
-search_access1(path, mode, errnop)
- const char *path;
- int mode;
- int *errnop; /* set if candidate found, but not suitable */
-{
- int ret, err = 0;
- struct stat statb;
-
- if (stat(path, &statb) < 0)
- return -1;
- ret = eaccess(path, mode);
- if (ret < 0)
- err = errno; /* File exists, but we can't access it */
- else if (!S_ISREG(statb.st_mode)) {
- ret = -1;
- err = S_ISDIR(statb.st_mode) ? EISDIR : EACCES;
- }
- if (err && errnop)
- *errnop = err;
- return ret;
-}
-#endif /* OS2 */
-
-/*
- * search for command with PATH
- */
-char *
-search(name, path, mode, errnop)
- const char *name;
- const char *path;
- int mode; /* R_OK or X_OK */
- int *errnop; /* set if candidate found, but not suitable */
-{
- const char *sp, *p;
- char *xp;
- XString xs;
- int namelen;
-
- if (errnop)
- *errnop = 0;
-#ifdef OS2
- /* Xinit() allocates 8 additional bytes, so appended suffixes won't
- * overflow the memory.
- */
- namelen = strlen(name) + 1;
- Xinit(xs, xp, namelen, ATEMP);
- memcpy(Xstring(xs, xp), name, namelen);
-
- if (ksh_strchr_dirsep(name)) {
- if (search_access(Xstring(xs, xp), mode, errnop) >= 0)
- return Xstring(xs, xp); /* not Xclose() - see above */
- Xfree(xs, xp);
- return NULL;
- }
-
- /* Look in current context always. (os2 style) */
- if (search_access(Xstring(xs, xp), mode, errnop) == 0)
- return Xstring(xs, xp); /* not Xclose() - xp may be wrong */
-#else /* OS2 */
- if (ksh_strchr_dirsep(name)) {
- if (search_access(name, mode, errnop) == 0)
- return (char *) name;
- return NULL;
- }
-
- namelen = strlen(name) + 1;
- Xinit(xs, xp, 128, ATEMP);
-#endif /* OS2 */
-
- sp = path;
- while (sp != NULL) {
- xp = Xstring(xs, xp);
- if (!(p = strchr(sp, PATHSEP)))
- p = sp + strlen(sp);
- if (p != sp) {
- XcheckN(xs, xp, p - sp);
- memcpy(xp, sp, p - sp);
- xp += p - sp;
- *xp++ = DIRSEP;
- }
- sp = p;
- XcheckN(xs, xp, namelen);
- memcpy(xp, name, namelen);
- if (search_access(Xstring(xs, xp), mode, errnop) == 0)
-#ifdef OS2
- return Xstring(xs, xp); /* Not Xclose() - see above */
-#else /* OS2 */
- return Xclose(xs, xp + namelen);
-#endif /* OS2 */
- if (*sp++ == '\0')
- sp = NULL;
- }
- Xfree(xs, xp);
- return NULL;
-}
-
-static int
-call_builtin(tp, wp)
- struct tbl *tp;
- char **wp;
-{
- int rv;
-
- builtin_argv0 = wp[0];
- builtin_flag = tp->flag;
- shf_reopen(1, SHF_WR, shl_stdout);
- shl_stdout_ok = 1;
- ksh_getopt_reset(&builtin_opt, GF_ERROR);
- rv = (*tp->val.f)(wp);
- shf_flush(shl_stdout);
- shl_stdout_ok = 0;
- builtin_flag = 0;
- builtin_argv0 = (char *) 0;
- return rv;
-}
-
-/*
- * set up redirection, saving old fd's in e->savefd
- */
-static int
-iosetup(iop, tp)
- register struct ioword *iop;
- struct tbl *tp;
-{
- register int u = -1;
- char *cp = iop->name;
- int iotype = iop->flag & IOTYPE;
- int do_open = 1, do_close = 0, UNINITIALIZED(flags);
- struct ioword iotmp;
- struct stat statb;
-
- if (iotype != IOHERE)
- cp = evalonestr(cp, DOTILDE|(Flag(FTALKING) ? DOGLOB : 0));
-
- /* Used for tracing and error messages to print expanded cp */
- iotmp = *iop;
- iotmp.name = (iotype == IOHERE) ? (char *) 0 : cp;
- iotmp.flag |= IONAMEXP;
-
- if (Flag(FXTRACE))
- shellf("%s%s\n",
- PS4_SUBSTITUTE(str_val(global("PS4"))),
- snptreef((char *) 0, 32, "%R", &iotmp));
-
- switch (iotype) {
- case IOREAD:
- flags = O_RDONLY;
- break;
-
- case IOCAT:
- flags = O_WRONLY | O_APPEND | O_CREAT;
- break;
-
- case IOWRITE:
- flags = O_WRONLY | O_CREAT | O_TRUNC;
- if (Flag(FNOCLOBBER) && !(iop->flag & IOCLOB)
- && (stat(cp, &statb) < 0 || S_ISREG(statb.st_mode)))
- flags |= O_EXCL;
- break;
-
- case IORDWR:
- flags = O_RDWR | O_CREAT;
- break;
-
- case IOHERE:
- do_open = 0;
- /* herein() returns -2 if error has been printed */
- u = herein(cp, iop->flag & IOEVAL);
- /* cp may have wrong name */
- break;
-
- case IODUP:
- {
- const char *emsg;
-
- do_open = 0;
- if (*cp == '-' && !cp[1]) {
- u = 1009; /* prevent error return below */
- do_close = 1;
- } else if ((u = check_fd(cp,
- X_OK | ((iop->flag & IORDUP) ? R_OK : W_OK),
- &emsg)) < 0)
- {
- warningf(TRUE, "%s: %s",
- snptreef((char *) 0, 32, "%R", &iotmp), emsg);
- return -1;
- }
- break;
- }
- }
- if (do_open) {
- if (Flag(FRESTRICTED) && (flags & O_CREAT)) {
- warningf(TRUE, "%s: restricted", cp);
- return -1;
- }
- u = open(cp, flags, 0666);
-#ifdef OS2
- if (u < 0 && strcmp(cp, "/dev/null") == 0)
- u = open("nul", flags, 0666);
-#endif /* OS2 */
- }
- if (u < 0) {
- /* herein() may already have printed message */
- if (u == -1)
- warningf(TRUE, "cannot %s %s: %s",
- iotype == IODUP ? "dup"
- : (iotype == IOREAD || iotype == IOHERE) ?
- "open" : "create", cp, strerror(errno));
- return -1;
- }
- /* Do not save if it has already been redirected (i.e. "cat >x >y"). */
- if (e->savefd[iop->unit] == 0)
- /* c_exec() assumes e->savefd[fd] set for any redirections.
- * Ask savefd() not to close iop->unit - allows error messages
- * to be seen if iop->unit is 2; also means we can't lose
- * the fd (eg, both dup2 below and dup2 in restfd() failing).
- */
- e->savefd[iop->unit] = savefd(iop->unit, 1);
-
- if (do_close)
- close(iop->unit);
- else if (u != iop->unit) {
- if (ksh_dup2(u, iop->unit, TRUE) < 0) {
- warningf(TRUE,
- "could not finish (dup) redirection %s: %s",
- snptreef((char *) 0, 32, "%R", &iotmp),
- strerror(errno));
- if (iotype != IODUP)
- close(u);
- return -1;
- }
- if (iotype != IODUP)
- close(u);
-#ifdef KSH
- /* Touching any co-process fd in an empty exec
- * causes the shell to close its copies
- */
- else if (tp && tp->type == CSHELL && tp->val.f == c_exec) {
- if (iop->flag & IORDUP) /* possible exec <&p */
- coproc_read_close(u);
- else /* possible exec >&p */
- coproc_write_close(u);
- }
-#endif /* KSH */
- }
- if (u == 2) /* Clear any write errors */
- shf_reopen(2, SHF_WR, shl_out);
- return 0;
-}
-
-/*
- * open here document temp file.
- * if unquoted here, expand here temp file into second temp file.
- */
-static int
-herein(hname, sub)
- char *hname;
- int sub;
-{
- int fd;
-
- /* ksh -c 'cat << EOF' can cause this... */
- if (hname == (char *) 0) {
- warningf(TRUE, "here document missing");
- return -2; /* special to iosetup(): don't print error */
- }
- if (sub) {
- char *cp;
- struct source *s, *volatile osource = source;
- struct temp *h;
- struct shf *volatile shf;
- int i;
-
- /* must be before newenv() 'cause shf uses ATEMP */
- shf = shf_open(hname, O_RDONLY, 0, SHF_MAPHI|SHF_CLEXEC);
- if (shf == NULL)
- return -1;
- newenv(E_ERRH);
- i = ksh_sigsetjmp(e->jbuf, 0);
- if (i) {
- if (shf)
- shf_close(shf);
- source = osource;
- quitenv(); /* after shf_close() due to alloc */
- return -2; /* special to iosetup(): don't print error */
- }
- /* set up yylex input from here file */
- s = pushs(SFILE, ATEMP);
- s->u.shf = shf;
- source = s;
- if (yylex(ONEWORD) != LWORD)
- internal_errorf(1, "herein: yylex");
- shf_close(shf);
- shf = (struct shf *) 0;
- cp = evalstr(yylval.cp, 0);
-
- /* write expanded input to another temp file */
- h = maketemp(ATEMP);
- h->next = e->temps; e->temps = h;
- if (!(shf = h->shf) || (fd = open(h->name, O_RDONLY, 0)) < 0)
- /* shf closeed by error handler */
- errorf("%s: %s", h->name, strerror(errno));
- shf_puts(cp, shf);
- if (shf_close(shf) == EOF) {
- close(fd);
- shf = (struct shf *) 0;
- errorf("error writing %s: %s", h->name,
- strerror(errno));
- }
- shf = (struct shf *) 0;
-
- quitenv();
- } else {
- fd = open(hname, O_RDONLY, 0);
- if (fd < 0)
- return -1;
- }
-
- return fd;
-}
-
-#if defined(KSH) || defined(EDIT)
-/*
- * ksh special - the select command processing section
- * print the args in column form - assuming that we can
- */
-static char *
-do_selectargs(ap, print_menu)
- register char **ap;
- bool_t print_menu;
-{
- static const char *const read_args[] = {
- "read", "-r", "REPLY", (char *) 0
- };
- char *s;
- int i, argct;
-
- for (argct = 0; ap[argct]; argct++)
- ;
- while (1) {
- /* Menu is printed if
- * - this is the first time around the select loop
- * - the user enters a blank line
- * - the REPLY parameter is empty
- */
- if (print_menu || !*str_val(global("REPLY")))
- pr_menu(ap);
- shellf("%s", str_val(global("PS3")));
- if (call_builtin(findcom("read", FC_BI), (char **) read_args))
- return (char *) 0;
- s = str_val(global("REPLY"));
- if (*s) {
- i = atoi(s);
- return (i >= 1 && i <= argct) ? ap[i - 1] : null;
- }
- print_menu = 1;
- }
-}
-
-struct select_menu_info {
- char *const *args;
- int arg_width;
- int num_width;
-} info;
-
-static char *select_fmt_entry ARGS((void *arg, int i, char *buf, int buflen));
-
-/* format a single select menu item */
-static char *
-select_fmt_entry(arg, i, buf, buflen)
- void *arg;
- int i;
- char *buf;
- int buflen;
-{
- struct select_menu_info *smi = (struct select_menu_info *) arg;
-
- shf_snprintf(buf, buflen, "%*d) %s",
- smi->num_width, i + 1, smi->args[i]);
- return buf;
-}
-
-/*
- * print a select style menu
- */
-int
-pr_menu(ap)
- char *const *ap;
-{
- struct select_menu_info smi;
- char *const *pp;
- int nwidth, dwidth;
- int i, n;
-
- /* Width/column calculations were done once and saved, but this
- * means select can't be used recursively so we re-calculate each
- * time (could save in a structure that is returned, but its probably
- * not worth the bother).
- */
-
- /*
- * get dimensions of the list
- */
- for (n = 0, nwidth = 0, pp = ap; *pp; n++, pp++) {
- i = strlen(*pp);
- nwidth = (i > nwidth) ? i : nwidth;
- }
- /*
- * we will print an index of the form
- * %d)
- * in front of each entry
- * get the max width of this
- */
- for (i = n, dwidth = 1; i >= 10; i /= 10)
- dwidth++;
-
- smi.args = ap;
- smi.arg_width = nwidth;
- smi.num_width = dwidth;
- print_columns(shl_out, n, select_fmt_entry, (void *) &smi,
- dwidth + nwidth + 2);
-
- return n;
-}
-#endif /* KSH || EDIT */
-#ifdef KSH
-
-/*
- * [[ ... ]] evaluation routines
- */
-
-extern const char *const dbtest_tokens[];
-extern const char db_close[];
-
-/* Test if the current token is a whatever. Accepts the current token if
- * it is. Returns 0 if it is not, non-zero if it is (in the case of
- * TM_UNOP and TM_BINOP, the returned value is a Test_op).
- */
-static int
-dbteste_isa(te, meta)
- Test_env *te;
- Test_meta meta;
-{
- int ret = 0;
- int uqword;
- char *p;
-
- if (!*te->pos.wp)
- return meta == TM_END;
-
- /* unquoted word? */
- for (p = *te->pos.wp; *p == CHAR; p += 2)
- ;
- uqword = *p == EOS;
-
- if (meta == TM_UNOP || meta == TM_BINOP) {
- if (uqword) {
- char buf[8]; /* longer than the longest operator */
- char *q = buf;
- for (p = *te->pos.wp; *p == CHAR
- && q < &buf[sizeof(buf) - 1];
- p += 2)
- *q++ = p[1];
- *q = '\0';
- ret = (int) test_isop(te, meta, buf);
- }
- } else if (meta == TM_END)
- ret = 0;
- else
- ret = uqword
- && strcmp(*te->pos.wp, dbtest_tokens[(int) meta]) == 0;
-
- /* Accept the token? */
- if (ret)
- te->pos.wp++;
-
- return ret;
-}
-
-static const char *
-dbteste_getopnd(te, op, do_eval)
- Test_env *te;
- Test_op op;
- int do_eval;
-{
- char *s = *te->pos.wp;
-
- if (!s)
- return (char *) 0;
-
- te->pos.wp++;
-
- if (!do_eval)
- return null;
-
- if (op == TO_STEQL || op == TO_STNEQ)
- s = evalstr(s, DOTILDE | DOPAT);
- else
- s = evalstr(s, DOTILDE);
-
- return s;
-}
-
-static int
-dbteste_eval(te, op, opnd1, opnd2, do_eval)
- Test_env *te;
- Test_op op;
- const char *opnd1;
- const char *opnd2;
- int do_eval;
-{
- return test_eval(te, op, opnd1, opnd2, do_eval);
-}
-
-static void
-dbteste_error(te, offset, msg)
- Test_env *te;
- int offset;
- const char *msg;
-{
- te->flags |= TEF_ERROR;
- internal_errorf(0, "dbteste_error: %s (offset %d)", msg, offset);
-}
-#endif /* KSH */
diff --git a/bin/pdksh/expand.h b/bin/pdksh/expand.h
deleted file mode 100644
index d0ab5937c1d..00000000000
--- a/bin/pdksh/expand.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/* $OpenBSD: expand.h,v 1.1 1996/08/14 06:19:11 downsj Exp $ */
-
-/*
- * Expanding strings
- */
-
-
-#if 0 /* Usage */
- XString xs;
- char *xp;
-
- Xinit(xs, xp, 128, ATEMP); /* allocate initial string */
- while ((c = generate()) {
- Xcheck(xs, xp); /* expand string if neccessary */
- Xput(xs, xp, c); /* add character */
- }
- return Xclose(xs, xp); /* resize string */
-/*
- * NOTE:
- * The Xcheck and Xinit macros have a magic + 8 in the lengths. This is
- * so that you can put up to 4 characters in a XString before calling
- * Xcheck. (See yylex in lex.c)
- */
-#endif /* 0 */
-
-typedef struct XString {
- char *end, *beg; /* end, begin of string */
- size_t len; /* length */
- Area *areap; /* area to allocate/free from */
-} XString;
-
-typedef char * XStringP;
-
-/* initialize expandable string */
-#define Xinit(xs, xp, length, area) do { \
- (xs).len = length; \
- (xs).areap = (area); \
- (xs).beg = alloc((xs).len + 8, (xs).areap); \
- (xs).end = (xs).beg + (xs).len; \
- xp = (xs).beg; \
- } while (0)
-
-/* stuff char into string */
-#define Xput(xs, xp, c) (*xp++ = (c))
-
-/* check if there are at least n bytes left */
-#define XcheckN(xs, xp, n) do { \
- int more = ((xp) + (n)) - (xs).end; \
- if (more > 0) \
- xp = Xcheck_grow_(&xs, xp, more); \
- } while (0)
-
-/* check for overflow, expand string */
-#define Xcheck(xs, xp) XcheckN(xs, xp, 1)
-
-/* free string */
-#define Xfree(xs, xp) afree((void*) (xs).beg, (xs).areap)
-
-/* close, return string */
-#define Xclose(xs, xp) (char*) aresize((void*)(xs).beg, \
- (size_t)((xp) - (xs).beg), (xs).areap)
-/* begin of string */
-#define Xstring(xs, xp) ((xs).beg)
-
-#define Xnleft(xs, xp) ((xs).end - (xp)) /* may be less than 0 */
-#define Xlength(xs, xp) ((xp) - (xs).beg)
-#define Xsize(xs, xp) ((xs).end - (xs).beg)
-#define Xsavepos(xs, xp) ((xp) - (xs).beg)
-#define Xrestpos(xs, xp, n) ((xs).beg + (n))
-
-char * Xcheck_grow_ ARGS((XString *xsp, char *xp, int more));
-
-/*
- * expandable vector of generic pointers
- */
-
-typedef struct XPtrV {
- void **cur; /* next avail pointer */
- void **beg, **end; /* begin, end of vector */
-} XPtrV;
-
-#define XPinit(x, n) do { \
- register void **vp__; \
- vp__ = (void**) alloc(sizeofN(void*, n), ATEMP); \
- (x).cur = (x).beg = vp__; \
- (x).end = vp__ + n; \
- } while (0)
-
-#define XPput(x, p) do { \
- if ((x).cur >= (x).end) { \
- int n = XPsize(x); \
- (x).beg = (void**) aresize((void*) (x).beg, \
- sizeofN(void*, n*2), ATEMP); \
- (x).cur = (x).beg + n; \
- (x).end = (x).cur + n; \
- } \
- *(x).cur++ = (p); \
- } while (0)
-
-#define XPptrv(x) ((x).beg)
-#define XPsize(x) ((x).cur - (x).beg)
-
-#define XPclose(x) (void**) aresize((void*)(x).beg, \
- sizeofN(void*, XPsize(x)), ATEMP)
-
-#define XPfree(x) afree((void*) (x).beg, ATEMP)
diff --git a/bin/pdksh/expr.c b/bin/pdksh/expr.c
deleted file mode 100644
index 775d7ee44dd..00000000000
--- a/bin/pdksh/expr.c
+++ /dev/null
@@ -1,596 +0,0 @@
-/* $OpenBSD: expr.c,v 1.4 1997/06/19 13:58:41 kstailey Exp $ */
-
-/*
- * Korn expression evaluation
- */
-/*
- * todo: better error handling: if in builtin, should be builtin error, etc.
- */
-
-#include "sh.h"
-#include <ctype.h>
-
-
-/* The order of these enums is constrained by the order of opinfo[] */
-enum token {
- /* some (long) unary operators */
- O_PLUSPLUS = 0, O_MINUSMINUS,
- /* binary operators */
- O_EQ, O_NE,
- /* assignments are assumed to be in range O_ASN .. O_BORASN */
- O_ASN, O_TIMESASN, O_DIVASN, O_MODASN, O_PLUSASN, O_MINUSASN,
- O_LSHIFTASN, O_RSHIFTASN, O_BANDASN, O_BXORASN, O_BORASN,
- O_LSHIFT, O_RSHIFT,
- O_LE, O_GE, O_LT, O_GT,
- O_LAND,
- O_LOR,
- O_TIMES, O_DIV, O_MOD,
- O_PLUS, O_MINUS,
- O_BAND,
- O_BXOR,
- O_BOR,
- O_TERN,
- O_COMMA,
- /* things after this aren't used as binary operators */
- /* unary that are not also binaries */
- O_BNOT, O_LNOT,
- /* misc */
- OPEN_PAREN, CLOSE_PAREN, CTERN,
- /* things that don't appear in the opinfo[] table */
- VAR, LIT, END, BAD
- };
-#define IS_BINOP(op) (((int)op) >= O_EQ && ((int)op) <= O_COMMA)
-#define IS_ASSIGNOP(op) ((int)(op) >= (int)O_ASN && (int)(op) <= (int)O_BORASN)
-
-enum prec {
- P_PRIMARY = 0, /* VAR, LIT, (), ~ ! - + */
- P_MULT, /* * / % */
- P_ADD, /* + - */
- P_SHIFT, /* << >> */
- P_RELATION, /* < <= > >= */
- P_EQUALITY, /* == != */
- P_BAND, /* & */
- P_BXOR, /* ^ */
- P_BOR, /* | */
- P_LAND, /* && */
- P_LOR, /* || */
- P_TERN, /* ?: */
- P_ASSIGN, /* = *= /= %= += -= <<= >>= &= ^= |= */
- P_COMMA /* , */
- };
-#define MAX_PREC P_COMMA
-
-struct opinfo {
- char name[4];
- int len; /* name length */
- enum prec prec; /* precidence: lower is higher */
-};
-
-/* Tokens in this table must be ordered so the longest are first
- * (eg, += before +). If you change something, change the order
- * of enum token too.
- */
-static const struct opinfo opinfo[] = {
- { "++", 2, P_PRIMARY }, /* before + */
- { "--", 2, P_PRIMARY }, /* before - */
- { "==", 2, P_EQUALITY }, /* before = */
- { "!=", 2, P_EQUALITY }, /* before ! */
- { "=", 1, P_ASSIGN }, /* keep assigns in a block */
- { "*=", 2, P_ASSIGN },
- { "/=", 2, P_ASSIGN },
- { "%=", 2, P_ASSIGN },
- { "+=", 2, P_ASSIGN },
- { "-=", 2, P_ASSIGN },
- { "<<=", 3, P_ASSIGN },
- { ">>=", 3, P_ASSIGN },
- { "&=", 2, P_ASSIGN },
- { "^=", 2, P_ASSIGN },
- { "|=", 2, P_ASSIGN },
- { "<<", 2, P_SHIFT },
- { ">>", 2, P_SHIFT },
- { "<=", 2, P_RELATION },
- { ">=", 2, P_RELATION },
- { "<", 1, P_RELATION },
- { ">", 1, P_RELATION },
- { "&&", 2, P_LAND },
- { "||", 2, P_LOR },
- { "*", 1, P_MULT },
- { "/", 1, P_MULT },
- { "%", 1, P_MULT },
- { "+", 1, P_ADD },
- { "-", 1, P_ADD },
- { "&", 1, P_BAND },
- { "^", 1, P_BXOR },
- { "|", 1, P_BOR },
- { "?", 1, P_TERN },
- { ",", 1, P_COMMA },
- { "~", 1, P_PRIMARY },
- { "!", 1, P_PRIMARY },
- { "(", 1, P_PRIMARY },
- { ")", 1, P_PRIMARY },
- { ":", 1, P_PRIMARY },
- { "", 0, P_PRIMARY } /* end of table */
- };
-
-
-typedef struct expr_state Expr_state;
-struct expr_state {
- const char *expression; /* expression being evaluated */
- const char *tokp; /* lexical position */
- enum token tok; /* token from token() */
- int noassign; /* don't do assigns (for ?:,&&,||) */
- struct tbl *val; /* value from token() */
- struct tbl *evaling; /* variable that is being recursively
- * expanded (EXPRINEVAL flag set)
- */
- Expr_state *volatile prev; /* previous state */
-};
-
-enum error_type { ET_UNEXPECTED, ET_BADLIT, ET_RECURSIVE,
- ET_LVALUE, ET_RDONLY, ET_STR };
-
-static Expr_state *es;
-
-static void evalerr ARGS((enum error_type type, const char *str))
- GCC_FUNC_ATTR(noreturn);
-static struct tbl *evalexpr ARGS((enum prec prec));
-static void token ARGS((void));
-static struct tbl *do_ppmm ARGS((enum token op, struct tbl *vasn,
- bool_t is_prefix));
-static void assign_check ARGS((enum token op, struct tbl *vasn));
-static struct tbl *tempvar ARGS((void));
-static struct tbl *intvar ARGS((struct tbl *vp));
-
-/*
- * parse and evalute expression
- */
-int
-evaluate(expr, rval, error_ok)
- const char *expr;
- long *rval;
- int error_ok;
-{
- struct tbl v;
- int ret;
-
- v.flag = DEFINED|INTEGER;
- v.type = 0;
- ret = v_evaluate(&v, expr, error_ok);
- *rval = v.val.i;
- return ret;
-}
-
-/*
- * parse and evalute expression, storing result in vp.
- */
-int
-v_evaluate(vp, expr, error_ok)
- struct tbl *vp;
- const char *expr;
- volatile int error_ok;
-{
- struct tbl *v;
- Expr_state curstate;
- int i;
-
- /* save state to allow recursive calls */
- curstate.expression = curstate.tokp = expr;
- curstate.noassign = 0;
- curstate.prev = es;
- curstate.evaling = (struct tbl *) 0;
- es = &curstate;
-
- newenv(E_ERRH);
- i = ksh_sigsetjmp(e->jbuf, 0);
- if (i) {
- /* Clear EXPRINEVAL in of any variables we were playing with */
- if (curstate.evaling)
- curstate.evaling->flag &= ~EXPRINEVAL;
- quitenv();
- es = curstate.prev;
- if (i == LAEXPR) {
- if (error_ok)
- return 0;
- errorf(null);
- }
- unwind(i);
- /*NOTREACHED*/
- }
-
- token();
-#if 1 /* ifdef-out to disallow empty expressions to be treated as 0 */
- if (es->tok == END) {
- es->tok = LIT;
- es->val = tempvar();
- }
-#endif /* 0 */
- v = intvar(evalexpr(MAX_PREC));
-
- if (es->tok != END)
- evalerr(ET_UNEXPECTED, (char *) 0);
-
- if (vp->flag & INTEGER)
- setint_v(vp, v);
- else
- setstr(vp, str_val(v));
-
- es = curstate.prev;
- quitenv();
-
- return 1;
-}
-
-static void
-evalerr(type, str)
- enum error_type type;
- const char *str;
-{
- char tbuf[2];
- const char *s;
-
- switch (type) {
- case ET_UNEXPECTED:
- switch (es->tok) {
- case VAR:
- s = es->val->name;
- break;
- case LIT:
- s = str_val(es->val);
- break;
- case END:
- s = "end of expression";
- break;
- case BAD:
- tbuf[0] = *es->tokp;
- tbuf[1] = '\0';
- s = tbuf;
- break;
- default:
- s = opinfo[(int)es->tok].name;
- }
- warningf(TRUE, "%s: unexpected `%s'", es->expression, s);
- break;
-
- case ET_BADLIT:
- warningf(TRUE, "%s: bad number `%s'", es->expression, str);
- break;
-
- case ET_RECURSIVE:
- warningf(TRUE, "%s: expression recurses on parameter `%s'",
- es->expression, str);
- break;
-
- case ET_LVALUE:
- warningf(TRUE, "%s: %s requires lvalue",
- es->expression, str);
- break;
-
- case ET_RDONLY:
- warningf(TRUE, "%s: %s applied to read only variable",
- es->expression, str);
- break;
-
- default: /* keep gcc happy */
- case ET_STR:
- warningf(TRUE, "%s: %s", es->expression, str);
- break;
- }
- unwind(LAEXPR);
-}
-
-static struct tbl *
-evalexpr(prec)
- enum prec prec;
-{
- register struct tbl *vl, UNINITIALIZED(*vr), *vasn;
- register enum token op;
- long UNINITIALIZED(res);
-
- if (prec == P_PRIMARY) {
- op = es->tok;
- if (op == O_BNOT || op == O_LNOT || op == O_MINUS
- || op == O_PLUS)
- {
- token();
- vl = intvar(evalexpr(P_PRIMARY));
- if (op == O_BNOT)
- vl->val.i = ~vl->val.i;
- else if (op == O_LNOT)
- vl->val.i = !vl->val.i;
- else if (op == O_MINUS)
- vl->val.i = -vl->val.i;
- /* op == O_PLUS is a no-op */
- } else if (op == OPEN_PAREN) {
- token();
- vl = evalexpr(MAX_PREC);
- if (es->tok != CLOSE_PAREN)
- evalerr(ET_STR, "missing )");
- token();
- } else if (op == O_PLUSPLUS || op == O_MINUSMINUS) {
- token();
- vl = do_ppmm(op, es->val, TRUE);
- token();
- } else if (op == VAR || op == LIT) {
- vl = es->val;
- token();
- } else {
- evalerr(ET_UNEXPECTED, (char *) 0);
- /*NOTREACHED*/
- }
- if (es->tok == O_PLUSPLUS || es->tok == O_MINUSMINUS) {
- vl = do_ppmm(es->tok, vl, FALSE);
- token();
- }
- return vl;
- }
- vl = evalexpr(((int) prec) - 1);
- for (op = es->tok; IS_BINOP(op) && opinfo[(int) op].prec == prec;
- op = es->tok)
- {
- token();
- vasn = vl;
- if (op != O_ASN) /* vl may not have a value yet */
- vl = intvar(vl);
- if (IS_ASSIGNOP(op)) {
- assign_check(op, vasn);
- vr = intvar(evalexpr(P_ASSIGN));
- } else if (op != O_TERN && op != O_LAND && op != O_LOR)
- vr = intvar(evalexpr(((int) prec) - 1));
- if ((op == O_DIV || op == O_MOD || op == O_DIVASN
- || op == O_MODASN) && vr->val.i == 0)
- {
- if (es->noassign)
- vr->val.i = 1;
- else
- evalerr(ET_STR, "zero divisor");
- }
- switch ((int) op) {
- case O_TIMES:
- case O_TIMESASN:
- res = vl->val.i * vr->val.i;
- break;
- case O_DIV:
- case O_DIVASN:
- res = vl->val.i / vr->val.i;
- break;
- case O_MOD:
- case O_MODASN:
- res = vl->val.i % vr->val.i;
- break;
- case O_PLUS:
- case O_PLUSASN:
- res = vl->val.i + vr->val.i;
- break;
- case O_MINUS:
- case O_MINUSASN:
- res = vl->val.i - vr->val.i;
- break;
- case O_LSHIFT:
- case O_LSHIFTASN:
- res = vl->val.i << vr->val.i;
- break;
- case O_RSHIFT:
- case O_RSHIFTASN:
- res = vl->val.i >> vr->val.i;
- break;
- case O_LT:
- res = vl->val.i < vr->val.i;
- break;
- case O_LE:
- res = vl->val.i <= vr->val.i;
- break;
- case O_GT:
- res = vl->val.i > vr->val.i;
- break;
- case O_GE:
- res = vl->val.i >= vr->val.i;
- break;
- case O_EQ:
- res = vl->val.i == vr->val.i;
- break;
- case O_NE:
- res = vl->val.i != vr->val.i;
- break;
- case O_BAND:
- case O_BANDASN:
- res = vl->val.i & vr->val.i;
- break;
- case O_BXOR:
- case O_BXORASN:
- res = vl->val.i ^ vr->val.i;
- break;
- case O_BOR:
- case O_BORASN:
- res = vl->val.i | vr->val.i;
- break;
- case O_LAND:
- if (!vl->val.i)
- es->noassign++;
- vr = intvar(evalexpr(((int) prec) - 1));
- res = vl->val.i && vr->val.i;
- if (!vl->val.i)
- es->noassign--;
- break;
- case O_LOR:
- if (vl->val.i)
- es->noassign++;
- vr = intvar(evalexpr(((int) prec) - 1));
- res = vl->val.i || vr->val.i;
- if (vl->val.i)
- es->noassign--;
- break;
- case O_TERN:
- {
- int e = vl->val.i != 0;
- if (!e)
- es->noassign++;
- vl = evalexpr(MAX_PREC);
- if (!e)
- es->noassign--;
- if (es->tok != CTERN)
- evalerr(ET_STR, "missing :");
- token();
- if (e)
- es->noassign++;
- vr = evalexpr(P_TERN);
- if (e)
- es->noassign--;
- vl = e ? vl : vr;
- }
- break;
- case O_ASN:
- res = vr->val.i;
- break;
- case O_COMMA:
- res = vr->val.i;
- break;
- }
- if (IS_ASSIGNOP(op)) {
- vr->val.i = res;
- if (vasn->flag & INTEGER)
- setint_v(vasn, vr);
- else
- setint(vasn, res);
- vl = vr;
- } else if (op != O_TERN)
- vl->val.i = res;
- }
- return vl;
-}
-
-static void
-token()
-{
- register const char *cp;
- register int c;
- char *tvar;
-
- /* skip white space */
- for (cp = es->tokp; (c = *cp), isspace(c); cp++)
- ;
- es->tokp = cp;
-
- if (c == '\0')
- es->tok = END;
- else if (letter(c)) {
- for (; letnum(c); c = *cp)
- cp++;
- if (c == '[') {
- int len;
-
- len = array_ref_len(cp);
- if (len == 0)
- evalerr(ET_STR, "missing ]");
- cp += len;
- }
- if (es->noassign) {
- es->val = tempvar();
- es->val->flag |= EXPRLVALUE;
- } else {
- tvar = str_nsave(es->tokp, cp - es->tokp, ATEMP);
- es->val = global(tvar);
- afree(tvar, ATEMP);
- }
- es->tok = VAR;
- } else if (digit(c)) {
- for (; c != '_' && (letnum(c) || c == '#'); c = *cp++)
- ;
- tvar = str_nsave(es->tokp, --cp - es->tokp, ATEMP);
- es->val = tempvar();
- es->val->flag &= ~INTEGER;
- es->val->type = 0;
- es->val->val.s = tvar;
- if (setint_v(es->val, es->val) == NULL)
- evalerr(ET_BADLIT, tvar);
- afree(tvar, ATEMP);
- es->tok = LIT;
- } else {
- int i, n0;
-
- for (i = 0; (n0 = opinfo[i].name[0]); i++)
- if (c == n0
- && strncmp(cp, opinfo[i].name, opinfo[i].len) == 0)
- {
- es->tok = (enum token) i;
- cp += opinfo[i].len;
- break;
- }
- if (!n0)
- es->tok = BAD;
- }
- es->tokp = cp;
-}
-
-/* Do a ++ or -- operation */
-static struct tbl *
-do_ppmm(op, vasn, is_prefix)
- enum token op;
- struct tbl *vasn;
- bool_t is_prefix;
-{
- struct tbl *vl;
- int oval;
-
- assign_check(op, vasn);
-
- vl = intvar(vasn);
- oval = op == O_PLUSPLUS ? vl->val.i++ : vl->val.i--;
- if (vasn->flag & INTEGER)
- setint_v(vasn, vl);
- else
- setint(vasn, vl->val.i);
- if (!is_prefix) /* undo the inc/dec */
- vl->val.i = oval;
-
- return vl;
-}
-
-static void
-assign_check(op, vasn)
- enum token op;
- struct tbl *vasn;
-{
- if (vasn->name[0] == '\0' && !(vasn->flag & EXPRLVALUE))
- evalerr(ET_LVALUE, opinfo[op].name);
- else if (vasn->flag & RDONLY)
- evalerr(ET_RDONLY, opinfo[op].name);
-}
-
-static struct tbl *
-tempvar()
-{
- register struct tbl *vp;
-
- vp = (struct tbl*) alloc(sizeof(struct tbl), ATEMP);
- vp->flag = ISSET|INTEGER;
- vp->type = 0;
- vp->areap = ATEMP;
- vp->val.i = 0;
- vp->name[0] = '\0';
- return vp;
-}
-
-/* cast (string) variable to temporary integer variable */
-static struct tbl *
-intvar(vp)
- register struct tbl *vp;
-{
- register struct tbl *vq;
-
- /* try to avoid replacing a temp var with another temp var */
- if (vp->name[0] == '\0'
- && (vp->flag & (ISSET|INTEGER|EXPRLVALUE)) == (ISSET|INTEGER))
- return vp;
-
- vq = tempvar();
- if (setint_v(vq, vp) == NULL) {
- if (vp->flag & EXPRINEVAL)
- evalerr(ET_RECURSIVE, vp->name);
- es->evaling = vp;
- vp->flag |= EXPRINEVAL;
- v_evaluate(vq, str_val(vp), FALSE);
- vp->flag &= ~EXPRINEVAL;
- es->evaling = (struct tbl *) 0;
- }
- return vq;
-}
diff --git a/bin/pdksh/history.c b/bin/pdksh/history.c
deleted file mode 100644
index f9c4b28e2e7..00000000000
--- a/bin/pdksh/history.c
+++ /dev/null
@@ -1,1193 +0,0 @@
-/* $OpenBSD: history.c,v 1.7 1997/06/19 13:58:42 kstailey Exp $ */
-
-/*
- * command history
- *
- * only implements in-memory history.
- */
-
-/*
- * This file contains
- * a) the original in-memory history mechanism
- * b) a simple file saving history mechanism done by sjg@zen
- * define EASY_HISTORY to get this
- * c) a more complicated mechanism done by pc@hillside.co.uk
- * that more closely follows the real ksh way of doing
- * things. You need to have the mmap system call for this
- * to work on your system
- */
-
-#include "sh.h"
-#include "ksh_stat.h"
-
-#ifdef HISTORY
-# ifdef EASY_HISTORY
-
-# ifndef HISTFILE
-# ifdef OS2
-# define HISTFILE "history.ksh"
-# else /* OS2 */
-# define HISTFILE ".pdksh_hist"
-# endif /* OS2 */
-# endif
-
-# else
-/* Defines and includes for the complicated case */
-
-# include <sys/file.h>
-# include <sys/mman.h>
-
-/*
- * variables for handling the data file
- */
-static int histfd;
-static int hsize;
-
-static int hist_count_lines ARGS((unsigned char *, int));
-static int hist_shrink ARGS((unsigned char *, int));
-static unsigned char *hist_skip_back ARGS((unsigned char *,int *,int));
-static void histload ARGS((Source *, unsigned char *, int));
-static void histinsert ARGS((Source *, int, unsigned char *));
-static void writehistfile ARGS((int, char *));
-static int sprinkle ARGS((int));
-
-# ifdef MAP_FILE
-# define MAP_FLAGS (MAP_FILE|MAP_PRIVATE)
-# else
-# define MAP_FLAGS MAP_PRIVATE
-# endif
-
-# endif /* of EASY_HISTORY */
-
-static int hist_execute ARGS((char *cmd));
-static int hist_replace ARGS((char **hp, const char *pat, const char *rep,
- int global));
-static char **hist_get ARGS((const char *str, int approx, int allow_cur));
-static char **hist_get_newest ARGS((int allow_cur));
-static char **hist_get_oldest ARGS(());
-static void histbackup ARGS((void));
-
-static char **current; /* current postition in history[] */
-static int curpos; /* current index in history[] */
-static char *hname; /* current name of history file */
-static int hstarted; /* set after hist_init() called */
-static Source *hist_source;
-
-
-int
-c_fc(wp)
- char **wp;
-{
- struct shf *shf;
- struct temp UNINITIALIZED(*tf);
- char *p, *editor = (char *) 0;
- int gflag = 0, lflag = 0, nflag = 0, sflag = 0, rflag = 0;
- int optc;
- char *first = (char *) 0, *last = (char *) 0;
- char **hfirst, **hlast, **hp;
-
- while ((optc = ksh_getopt(wp, &builtin_opt, "e:glnrs0,1,2,3,4,5,6,7,8,9,")) != EOF)
- switch (optc) {
- case 'e':
- p = builtin_opt.optarg;
- if (strcmp(p, "-") == 0)
- sflag++;
- else {
- editor = str_nsave(p, strlen(p) + 4, ATEMP);
- strcat(editor, " $_");
- }
- break;
- case 'g': /* non-at&t ksh */
- gflag++;
- break;
- case 'l':
- lflag++;
- break;
- case 'n':
- nflag++;
- break;
- case 'r':
- rflag++;
- break;
- case 's': /* posix version of -e - */
- sflag++;
- break;
- /* kludge city - accept -num as -- -num (kind of) */
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- p = shf_smprintf("-%c%s",
- optc, builtin_opt.optarg);
- if (!first)
- first = p;
- else if (!last)
- last = p;
- else {
- bi_errorf("too many arguments");
- return 1;
- }
- break;
- case '?':
- return 1;
- }
- wp += builtin_opt.optind;
-
- /* Substitute and execute command */
- if (sflag) {
- char *pat = (char *) 0, *rep = (char *) 0;
-
- if (editor || lflag || nflag || rflag) {
- bi_errorf("can't use -e, -l, -n, -r with -s (-e -)");
- return 1;
- }
-
- /* Check for pattern replacement argument */
- if (*wp && **wp && (p = strchr(*wp + 1, '='))) {
- pat = str_save(*wp, ATEMP);
- p = pat + (p - *wp);
- *p++ = '\0';
- rep = p;
- wp++;
- }
- /* Check for search prefix */
- if (!first && (first = *wp))
- wp++;
- if (last || *wp) {
- bi_errorf("too many arguments");
- return 1;
- }
-
- hp = first ? hist_get(first, FALSE, FALSE)
- : hist_get_newest(FALSE);
- if (!hp)
- return 1;
- return hist_replace(hp, pat, rep, gflag);
- }
-
- if (editor && (lflag || nflag)) {
- bi_errorf("can't use -l, -n with -e");
- return 1;
- }
-
- if (!first && (first = *wp))
- wp++;
- if (!last && (last = *wp))
- wp++;
- if (*wp) {
- bi_errorf("too many arguments");
- return 1;
- }
- if (!first) {
- hfirst = lflag ? hist_get("-16", TRUE, TRUE)
- : hist_get_newest(FALSE);
- if (!hfirst)
- return 1;
- /* can't fail if hfirst didn't fail */
- hlast = hist_get_newest(FALSE);
- } else {
- /* POSIX says not an error if first/last out of bounds
- * when range is specified; at&t ksh and pdksh allow out of
- * bounds for -l as well.
- */
- hfirst = hist_get(first, (lflag || last) ? TRUE : FALSE,
- lflag ? TRUE : FALSE);
- if (!hfirst)
- return 1;
- hlast = last ? hist_get(last, TRUE, lflag ? TRUE : FALSE)
- : (lflag ? hist_get_newest(FALSE) : hfirst);
- if (!hlast)
- return 1;
- }
- if (hfirst > hlast) {
- char **temp;
-
- temp = hfirst; hfirst = hlast; hlast = temp;
- rflag = !rflag; /* POSIX */
- }
-
- /* List history */
- if (lflag) {
- char *s, *t;
- const char *nfmt = nflag ? "\t" : "%d\t";
-
- for (hp = rflag ? hlast : hfirst;
- hp >= hfirst && hp <= hlast; hp += rflag ? -1 : 1)
- {
- shf_fprintf(shl_stdout, nfmt,
- hist_source->line - (int) (histptr - hp));
- /* print multi-line commands correctly */
- for (s = *hp; (t = strchr(s, '\n')); s = t)
- shf_fprintf(shl_stdout, "%.*s\t", ++t - s, s);
- shf_fprintf(shl_stdout, "%s\n", s);
- }
- shf_flush(shl_stdout);
- return 0;
- }
-
- /* Run editor on selected lines, then run resulting commands */
-
- tf = maketemp(ATEMP);
- tf->next = e->temps; e->temps = tf;
- if (!(shf = tf->shf)) {
- bi_errorf("cannot create temp file %s - %s",
- tf->name, strerror(errno));
- return 1;
- }
- for (hp = rflag ? hlast : hfirst;
- hp >= hfirst && hp <= hlast; hp += rflag ? -1 : 1)
- shf_fprintf(shf, "%s\n", *hp);
- if (shf_close(shf) == EOF) {
- bi_errorf("error writing temporary file - %s", strerror(errno));
- return 1;
- }
-
- if (!Flag(FSH))
- setstr(local("_", FALSE), tf->name);
-
- /* XXX: source should not get trashed by this.. */
- {
- Source *sold = source;
- int ret;
-
- ret = command(editor ? editor : "${FCEDIT:-/bin/ed} $_");
- source = sold;
- if (ret)
- return ret;
- }
-
- {
- struct stat statb;
- XString xs;
- char *xp;
- int n;
-
- if (!(shf = shf_open(tf->name, O_RDONLY, 0, 0))) {
- bi_errorf("cannot open temp file %s", tf->name);
- return 1;
- }
-
- n = fstat(shf_fileno(shf), &statb) < 0 ? 128
- : statb.st_size + 1;
- Xinit(xs, xp, n, hist_source->areap);
- while ((n = shf_read(xp, Xnleft(xs, xp), shf)) > 0) {
- xp += n;
- if (Xnleft(xs, xp) <= 0)
- XcheckN(xs, xp, Xlength(xs, xp));
- }
- if (n < 0) {
- bi_errorf("error reading temp file %s - %s",
- tf->name, strerror(shf_errno(shf)));
- shf_close(shf);
- return 1;
- }
- shf_close(shf);
- *xp = '\0';
- strip_nuls(Xstring(xs, xp), Xlength(xs, xp));
- return hist_execute(Xstring(xs, xp));
- }
-}
-
-/* Save cmd in history, execute cmd (cmd gets trashed) */
-static int
-hist_execute(cmd)
- char *cmd;
-{
- Source *sold;
- int ret;
- char *p, *q;
-
- histbackup();
-
- for (p = cmd; p; p = q) {
- if ((q = strchr(p, '\n'))) {
- *q++ = '\0'; /* kill the newline */
- if (!*q) /* ignore trailing newline */
- q = (char *) 0;
- }
-#ifdef EASY_HISTORY
- if (p != cmd)
- histappend(p, TRUE);
- else
-#endif /* EASY_HISTORY */
- histsave(++(hist_source->line), p, 1);
-
- shellf("%s\n", p); /* POSIX doesn't say this is done... */
- if ((p = q)) /* restore \n (trailing \n not restored) */
- q[-1] = '\n';
- }
-
- /* Commands are executed here instead of pushing them onto the
- * input 'cause posix says the redirection and variable assignments
- * in
- * X=y fc -e - 42 2> /dev/null
- * are to effect the repeated commands environment.
- */
- /* XXX: source should not get trashed by this.. */
- sold = source;
- ret = command(cmd);
- source = sold;
- return ret;
-}
-
-static int
-hist_replace(hp, pat, rep, global)
- char **hp;
- const char *pat;
- const char *rep;
- int global;
-{
- char *line;
-
- if (!pat)
- line = str_save(*hp, ATEMP);
- else {
- char *s, *s1;
- int pat_len = strlen(pat);
- int rep_len = strlen(rep);
- int len;
- XString xs;
- char *xp;
- int any_subst = 0;
-
- Xinit(xs, xp, 128, ATEMP);
- for (s = *hp; (s1 = strstr(s, pat))
- && (!any_subst || global) ; s = s1 + pat_len)
- {
- any_subst = 1;
- len = s1 - s;
- XcheckN(xs, xp, len + rep_len);
- memcpy(xp, s, len); /* first part */
- xp += len;
- memcpy(xp, rep, rep_len); /* replacement */
- xp += rep_len;
- }
- if (!any_subst) {
- bi_errorf("substitution failed");
- return 1;
- }
- len = strlen(s) + 1;
- XcheckN(xs, xp, len);
- memcpy(xp, s, len);
- xp += len;
- line = Xclose(xs, xp);
- }
- return hist_execute(line);
-}
-
-/*
- * get pointer to history given pattern
- * pattern is a number or string
- */
-static char **
-hist_get(str, approx, allow_cur)
- const char *str;
- int approx;
- int allow_cur;
-{
- char **hp = (char **) 0;
- int n;
-
- if (getn(str, &n)) {
- hp = histptr + (n < 0 ? n : (n - hist_source->line));
- if (hp < history) {
- if (approx)
- hp = hist_get_oldest();
- else {
- bi_errorf("%s: not in history", str);
- hp = (char **) 0;
- }
- } else if (hp > histptr) {
- if (approx)
- hp = hist_get_newest(allow_cur);
- else {
- bi_errorf("%s: not in history", str);
- hp = (char **) 0;
- }
- } else if (!allow_cur && hp == histptr) {
- bi_errorf("%s: invalid range", str);
- hp = (char **) 0;
- }
- } else {
- int anchored = *str == '?' ? (++str, 0) : 1;
-
- /* the -1 is to avoid the current fc command */
- n = findhist(histptr - history - 1, 0, str, anchored);
- if (n < 0) {
- bi_errorf("%s: not in history", str);
- hp = (char **) 0;
- } else
- hp = &history[n];
- }
- return hp;
-}
-
-/* Return a pointer to the newest command in the history */
-static char **
-hist_get_newest(allow_cur)
- int allow_cur;
-{
- if (histptr < history || (!allow_cur && histptr == history)) {
- bi_errorf("no history (yet)");
- return (char **) 0;
- }
- if (allow_cur)
- return histptr;
- return histptr - 1;
-}
-
-/* Return a pointer to the newest command in the history */
-static char **
-hist_get_oldest()
-{
- if (histptr <= history) {
- bi_errorf("no history (yet)");
- return (char **) 0;
- }
- return history;
-}
-
-/******************************/
-/* Back up over last histsave */
-/******************************/
-static void
-histbackup()
-{
- static int last_line = -1;
-
- if (histptr >= history && last_line != hist_source->line) {
- hist_source->line--;
- afree((void*)*histptr, APERM);
- histptr--;
- last_line = hist_source->line;
- }
-}
-
-/*
- * Return the current position.
- */
-char **
-histpos()
-{
- return current;
-}
-
-int
-histN()
-{
- return curpos;
-}
-
-int
-histnum(n)
- int n;
-{
- int last = histptr - history;
-
- if (n < 0 || n >= last) {
- current = histptr;
- curpos = last;
- return last;
- } else {
- current = &history[n];
- curpos = n;
- return n;
- }
-}
-
-/*
- * This will become unecessary if hist_get is modified to allow
- * searching from positions other than the end, and in either
- * direction.
- */
-int
-findhist(start, fwd, str, anchored)
- int start;
- int fwd;
- const char *str;
- int anchored;
-{
- char **hp;
- int maxhist = histptr - history;
- int incr = fwd ? 1 : -1;
- int len = strlen(str);
-
- if (start < 0 || start >= maxhist)
- start = maxhist;
-
- hp = &history[start];
- for (; hp >= history && hp <= histptr; hp += incr)
- if ((anchored && strncmp(*hp, str, len) == 0)
- || (!anchored && strstr(*hp, str)))
- return hp - history;
-
- return -1;
-}
-
-/*
- * set history
- * this means reallocating the dataspace
- */
-void
-sethistsize(n)
- int n;
-{
- if (n > 0 && n != histsize) {
- int cursize = histptr - history;
-
- /* save most recent history */
- if (n < cursize) {
- memmove(history, histptr - n, n * sizeof(char *));
- cursize = n;
- }
-
- history = (char **)aresize(history, n*sizeof(char *), APERM);
-
- histsize = n;
- histptr = history + cursize;
- }
-}
-
-/*
- * set history file
- * This can mean reloading/resetting/starting history file
- * maintenance
- */
-void
-sethistfile(name)
- const char *name;
-{
- /* if not started then nothing to do */
- if (hstarted == 0)
- return;
-
- /* if the name is the same as the name we have */
- if (hname && strcmp(hname, name) == 0)
- return;
-
- /*
- * its a new name - possibly
- */
-# ifdef EASY_HISTORY
- if (hname) {
- afree(hname, APERM);
- hname = NULL;
- }
-# else
- if (histfd) {
- /* yes the file is open */
- (void) close(histfd);
- histfd = 0;
- hsize = 0;
- afree(hname, APERM);
- hname = NULL;
- /* let's reset the history */
- histptr = history - 1;
- hist_source->line = 0;
- }
-# endif
-
- hist_init(hist_source);
-}
-
-/*
- * initialise the history vector
- */
-void
-init_histvec()
-{
- if (history == (char **)NULL) {
- histsize = HISTORYSIZE;
- history = (char **)alloc(histsize*sizeof (char *), APERM);
- histptr = history - 1;
- }
-}
-
-# ifdef EASY_HISTORY
-/*
- * save command in history
- */
-void
-histsave(lno, cmd, dowrite)
- int lno; /* ignored (compatibility with COMPLEX_HISTORY) */
- const char *cmd;
- int dowrite; /* ignored (compatibility with COMPLEX_HISTORY) */
-{
- register char **hp = histptr;
- char *cp;
-
- if (++hp >= history + histsize) { /* remove oldest command */
- afree((void*)history[0], APERM);
- memmove(history, history + 1,
- sizeof(history[0]) * (histsize - 1));
- hp = &history[histsize - 1];
- }
- *hp = str_save(cmd, APERM);
- /* trash trailing newline but allow imbedded newlines */
- cp = *hp + strlen(*hp);
- if (cp > *hp && cp[-1] == '\n')
- cp[-1] = '\0';
- histptr = hp;
-}
-
-/*
- * Append an entry to the last saved command. Used for multiline
- * commands
- */
-void
-histappend(cmd, nl_seperate)
- const char *cmd;
- int nl_seperate;
-{
- int hlen, clen;
- char *p;
-
- hlen = strlen(*histptr);
- clen = strlen(cmd);
- if (clen > 0 && cmd[clen-1] == '\n')
- clen--;
- p = *histptr = (char *) aresize(*histptr, hlen + clen + 2, APERM);
- p += hlen;
- if (nl_seperate)
- *p++ = '\n';
- memcpy(p, cmd, clen);
- p[clen] = '\0';
-}
-
-/*
- * 92-04-25 <sjg@zen>
- * A simple history file implementation.
- * At present we only save the history when we exit.
- * This can cause problems when there are multiple shells are
- * running under the same user-id. The last shell to exit gets
- * to save its history.
- */
-void
-hist_init(s)
- Source *s;
-{
- char *f;
- FILE *fh;
-
- if (Flag(FTALKING) == 0)
- return;
-
- hstarted = 1;
-
- hist_source = s;
-
- if ((f = str_val(global("HISTFILE"))) == NULL || *f == '\0') {
-# if 1 /* Don't use history file unless the user asks for it */
- hname = NULL;
- return;
-# else
- char *home = str_val(global("HOME"));
- int len;
-
- if (home == NULL)
- home = null;
- f = HISTFILE;
- hname = alloc(len = strlen(home) + strlen(f) + 2, APERM);
- shf_snprintf(hname, len, "%s/%s", home, f);
-# endif
- } else
- hname = str_save(f, APERM);
-
- if ((fh = fopen(hname, "r"))) {
- int pos = 0, nread = 0;
- int contin = 0; /* continuation of previous command */
- char *end;
- char hline[LINE + 1];
-
- while (1) {
- if (pos >= nread) {
- pos = 0;
- nread = fread(hline, 1, LINE, fh);
- if (nread <= 0)
- break;
- hline[nread] = '\0';
- }
- end = strchr(hline + pos, 0); /* will always succeed */
- if (contin)
- histappend(hline + pos, 0);
- else {
- hist_source->line++;
- histsave(0, hline + pos, 0);
- }
- pos = end - hline + 1;
- contin = end == &hline[nread];
- }
- fclose(fh);
- }
-}
-
-/*
- * save our history.
- * We check that we do not have more than we are allowed.
- * If the history file is read-only we do nothing.
- * Handy for having all shells start with a useful history set.
- */
-
-void
-hist_finish()
-{
- static int once;
- FILE *fh;
- register int i;
- register char **hp;
-
- if (once++)
- return;
- /* check how many we have */
- i = histptr - history;
- if (i >= histsize)
- hp = &histptr[-histsize];
- else
- hp = history;
- if (hname && (fh = fopen(hname, "w")))
- {
- for (i = 0; hp + i <= histptr && hp[i]; i++)
- fprintf(fh, "%s%c", hp[i], '\0');
- fclose(fh);
- }
-}
-
-# else /* EASY_HISTORY */
-
-/*
- * Routines added by Peter Collinson BSDI(Europe)/Hillside Systems to
- * a) permit HISTSIZE to control number of lines of history stored
- * b) maintain a physical history file
- *
- * It turns out that there is a lot of ghastly hackery here
- */
-
-
-/*
- * save command in history
- */
-void
-histsave(lno, cmd, dowrite)
- int lno;
- const char *cmd;
- int dowrite;
-{
- register char **hp;
- char *c, *cp;
-
- c = str_save(cmd, APERM);
- if ((cp = strchr(c, '\n')) != NULL)
- *cp = '\0';
-
- if (histfd && dowrite)
- writehistfile(lno, c);
-
- hp = histptr;
-
- if (++hp >= history + histsize) { /* remove oldest command */
- afree((void*)*history, APERM);
- for (hp = history; hp < history + histsize - 1; hp++)
- hp[0] = hp[1];
- }
- *hp = c;
- histptr = hp;
-}
-
-/*
- * Write history data to a file nominated by HISTFILE
- * if HISTFILE is unset then history still happens, but
- * the data is not written to a file
- * All copies of ksh looking at the file will maintain the
- * same history. This is ksh behaviour.
- *
- * This stuff uses mmap()
- * if your system ain't got it - then you'll have to undef HISTORYFILE
- */
-
-/*
- * Open a history file
- * Format is:
- * Bytes 1, 2: HMAGIC - just to check that we are dealing with
- * the correct object
- * Then follows a number of stored commands
- * Each command is
- * <command byte><command number(4 bytes)><bytes><null>
- */
-# define HMAGIC1 0xab
-# define HMAGIC2 0xcd
-# define COMMAND 0xff
-
-void
-hist_init(s)
- Source *s;
-{
- unsigned char *base;
- int lines;
- int fd;
-
- if (Flag(FTALKING) == 0)
- return;
-
- hstarted = 1;
-
- hist_source = s;
-
- hname = str_val(global("HISTFILE"));
- if (hname == NULL)
- return;
- hname = str_save(hname, APERM);
-
- retry:
- /* we have a file and are interactive */
- if ((fd = open(hname, O_RDWR|O_CREAT|O_APPEND, 0600)) < 0)
- return;
-
- histfd = savefd(fd, 0);
-
- (void) flock(histfd, LOCK_EX);
-
- hsize = lseek(histfd, 0L, SEEK_END);
-
- if (hsize == 0) {
- /* add magic */
- if (sprinkle(histfd)) {
- hist_finish();
- return;
- }
- }
- else if (hsize > 0) {
- /*
- * we have some data
- */
- base = (unsigned char *)mmap(0, hsize, PROT_READ, MAP_FLAGS, histfd, 0);
- /*
- * check on its validity
- */
- if ((int)base == -1 || *base != HMAGIC1 || base[1] != HMAGIC2) {
- if ((int)base != -1)
- munmap((caddr_t)base, hsize);
- hist_finish();
- unlink(hname);
- goto retry;
- }
- if (hsize > 2) {
- lines = hist_count_lines(base+2, hsize-2);
- if (lines > histsize) {
- /* we need to make the file smaller */
- if (hist_shrink(base, hsize))
- unlink(hname);
- munmap((caddr_t)base, hsize);
- hist_finish();
- goto retry;
- }
- }
- histload(hist_source, base+2, hsize-2);
- munmap((caddr_t)base, hsize);
- }
- (void) flock(histfd, LOCK_UN);
- hsize = lseek(histfd, 0L, SEEK_END);
-}
-
-typedef enum state {
- shdr, /* expecting a header */
- sline, /* looking for a null byte to end the line */
- sn1, /* bytes 1 to 4 of a line no */
- sn2, sn3, sn4,
-} State;
-
-static int
-hist_count_lines(base, bytes)
- register unsigned char *base;
- register int bytes;
-{
- State state = shdr;
- register lines = 0;
-
- while (bytes--) {
- switch (state)
- {
- case shdr:
- if (*base == COMMAND)
- state = sn1;
- break;
- case sn1:
- state = sn2; break;
- case sn2:
- state = sn3; break;
- case sn3:
- state = sn4; break;
- case sn4:
- state = sline; break;
- case sline:
- if (*base == '\0')
- lines++, state = shdr;
- }
- base++;
- }
- return lines;
-}
-
-/*
- * Shrink the history file to histsize lines
- */
-static int
-hist_shrink(oldbase, oldbytes)
- unsigned char *oldbase;
- int oldbytes;
-{
- int fd;
- char nfile[1024];
- struct stat statb;
- unsigned char *nbase = oldbase;
- int nbytes = oldbytes;
-
- nbase = hist_skip_back(nbase, &nbytes, histsize);
- if (nbase == NULL)
- return 1;
- if (nbase == oldbase)
- return 0;
-
- /*
- * create temp file
- */
- (void) shf_snprintf(nfile, sizeof(nfile), "%s.%d", hname, procpid);
- if ((fd = creat(nfile, 0600)) < 0)
- return 1;
-
- if (sprinkle(fd)) {
- close(fd);
- unlink(nfile);
- return 1;
- }
- if (write(fd, nbase, nbytes) != nbytes) {
- close(fd);
- unlink(nfile);
- return 1;
- }
- /*
- * worry about who owns this file
- */
- if (fstat(histfd, &statb) >= 0)
- fchown(fd, statb.st_uid, statb.st_gid);
- close(fd);
-
- /*
- * rename
- */
- if (rename(nfile, hname) < 0)
- return 1;
- return 0;
-}
-
-
-/*
- * find a pointer to the data `no' back from the end of the file
- * return the pointer and the number of bytes left
- */
-static unsigned char *
-hist_skip_back(base, bytes, no)
- unsigned char *base;
- int *bytes;
- int no;
-{
- register int lines = 0;
- register unsigned char *ep;
-
- for (ep = base + *bytes; --ep > base; ) {
- /* this doesn't really work: the 4 byte line number that is
- * encoded after the COMMAND byte can itself contain the
- * COMMAND byte....
- */
- for (; ep > base && *ep != COMMAND; ep--)
- ;
- if (ep == base)
- break;
- if (++lines == no) {
- *bytes = *bytes - ((char *)ep - (char *)base);
- return ep;
- }
- }
- return NULL;
-}
-
-/*
- * load the history structure from the stored data
- */
-static void
-histload(s, base, bytes)
- Source *s;
- register unsigned char *base;
- register int bytes;
-{
- State state;
- int lno;
- unsigned char *line;
-
- for (state = shdr; bytes-- > 0; base++) {
- switch (state) {
- case shdr:
- if (*base == COMMAND)
- state = sn1;
- break;
- case sn1:
- lno = (((*base)&0xff)<<24);
- state = sn2;
- break;
- case sn2:
- lno |= (((*base)&0xff)<<16);
- state = sn3;
- break;
- case sn3:
- lno |= (((*base)&0xff)<<8);
- state = sn4;
- break;
- case sn4:
- lno |= (*base)&0xff;
- line = base+1;
- state = sline;
- break;
- case sline:
- if (*base == '\0') {
- /* worry about line numbers */
- if (histptr >= history && lno-1 != s->line) {
- /* a replacement ? */
- histinsert(s, lno, line);
- }
- else {
- s->line = lno;
- histsave(lno, (char *)line, 0);
- }
- state = shdr;
- }
- }
- }
-}
-
-/*
- * Insert a line into the history at a specified number
- */
-static void
-histinsert(s, lno, line)
- Source *s;
- int lno;
- unsigned char *line;
-{
- register char **hp;
-
- if (lno >= s->line-(histptr-history) && lno <= s->line) {
- hp = &histptr[lno-s->line];
- if (*hp)
- afree((void*)*hp, APERM);
- *hp = str_save((char *)line, APERM);
- }
-}
-
-/*
- * write a command to the end of the history file
- * This *MAY* seem easy but it's also necessary to check
- * that the history file has not changed in size.
- * If it has - then some other shell has written to it
- * and we should read those commands to update our history
- */
-static void
-writehistfile(lno, cmd)
- int lno;
- char *cmd;
-{
- int sizenow;
- unsigned char *base;
- unsigned char *new;
- int bytes;
- char hdr[5];
-
- (void) flock(histfd, LOCK_EX);
- sizenow = lseek(histfd, 0L, SEEK_END);
- if (sizenow != hsize) {
- /*
- * Things have changed
- */
- if (sizenow > hsize) {
- /* someone has added some lines */
- bytes = sizenow - hsize;
- base = (unsigned char *)mmap(0, sizenow, PROT_READ, MAP_FLAGS, histfd, 0);
- if ((int)base == -1)
- goto bad;
- new = base + hsize;
- if (*new != COMMAND) {
- munmap((caddr_t)base, sizenow);
- goto bad;
- }
- hist_source->line--;
- histload(hist_source, new, bytes);
- hist_source->line++;
- lno = hist_source->line;
- munmap((caddr_t)base, sizenow);
- hsize = sizenow;
- } else {
- /* it has shrunk */
- /* but to what? */
- /* we'll give up for now */
- goto bad;
- }
- }
- /*
- * we can write our bit now
- */
- hdr[0] = COMMAND;
- hdr[1] = (lno>>24)&0xff;
- hdr[2] = (lno>>16)&0xff;
- hdr[3] = (lno>>8)&0xff;
- hdr[4] = lno&0xff;
- (void) write(histfd, hdr, 5);
- (void) write(histfd, cmd, strlen(cmd)+1);
- hsize = lseek(histfd, 0L, SEEK_END);
- (void) flock(histfd, LOCK_UN);
- return;
-bad:
- hist_finish();
-}
-
-void
-hist_finish()
-{
- (void) flock(histfd, LOCK_UN);
- (void) close(histfd);
- histfd = 0;
-}
-
-/*
- * add magic to the history file
- */
-static int
-sprinkle(fd)
- int fd;
-{
- static char mag[] = { HMAGIC1, HMAGIC2 };
-
- return(write(fd, mag, 2) != 2);
-}
-
-# endif
-#else /* HISTORY */
-
-/* No history to be compiled in: dummy routines to avoid lots more ifdefs */
-void
-init_histvec()
-{
-}
-void
-hist_init(s)
- Source *s;
-{
-}
-void
-hist_finish()
-{
-}
-void
-histsave(lno, cmd, dowrite)
- int lno;
- const char *cmd;
- int dowrite;
-{
- errorf("history not enabled");
-}
-#endif /* HISTORY */
diff --git a/bin/pdksh/io.c b/bin/pdksh/io.c
deleted file mode 100644
index 4a2f1cc88e2..00000000000
--- a/bin/pdksh/io.c
+++ /dev/null
@@ -1,473 +0,0 @@
-/* $OpenBSD: io.c,v 1.4 1997/06/19 13:58:42 kstailey Exp $ */
-
-/*
- * shell buffered IO and formatted output
- */
-
-#include <ctype.h>
-#include "sh.h"
-#include "ksh_stat.h"
-
-/*
- * formatted output functions
- */
-
-
-/* A shell error occured (eg, syntax error, etc.) */
-void
-#ifdef HAVE_PROTOTYPES
-errorf(const char *fmt, ...)
-#else
-errorf(fmt, va_alist)
- const char *fmt;
- va_dcl
-#endif
-{
- va_list va;
-
- shl_stdout_ok = 0; /* debugging: note that stdout not valid */
- exstat = 1;
- if (*fmt) {
- error_prefix(TRUE);
- SH_VA_START(va, fmt);
- shf_vfprintf(shl_out, fmt, va);
- va_end(va);
- shf_putchar('\n', shl_out);
- }
- shf_flush(shl_out);
- unwind(LERROR);
-}
-
-/* like errorf(), but no unwind is done */
-void
-#ifdef HAVE_PROTOTYPES
-warningf(int fileline, const char *fmt, ...)
-#else
-warningf(fileline, fmt, va_alist)
- int fileline;
- const char *fmt;
- va_dcl
-#endif
-{
- va_list va;
-
- error_prefix(fileline);
- SH_VA_START(va, fmt);
- shf_vfprintf(shl_out, fmt, va);
- va_end(va);
- shf_putchar('\n', shl_out);
- shf_flush(shl_out);
-}
-
-/* Used by built-in utilities to prefix shell and utility name to message
- * (also unwinds environments for special builtins).
- */
-void
-#ifdef HAVE_PROTOTYPES
-bi_errorf(const char *fmt, ...)
-#else
-bi_errorf(fmt, va_alist)
- const char *fmt;
- va_dcl
-#endif
-{
- va_list va;
-
- shl_stdout_ok = 0; /* debugging: note that stdout not valid */
- exstat = 1;
- if (*fmt) {
- error_prefix(TRUE);
- /* not set when main() calls parse_args() */
- if (builtin_argv0)
- shf_fprintf(shl_out, "%s: ", builtin_argv0);
- SH_VA_START(va, fmt);
- shf_vfprintf(shl_out, fmt, va);
- va_end(va);
- shf_putchar('\n', shl_out);
- }
- shf_flush(shl_out);
- /* POSIX special builtins and ksh special builtins cause
- * non-interactive shells to exit.
- * XXX odd use of KEEPASN; also may not want LERROR here
- */
- if ((builtin_flag & SPEC_BI)
- || (Flag(FPOSIX) && (builtin_flag & KEEPASN)))
- {
- builtin_argv0 = (char *) 0;
- unwind(LERROR);
- }
-}
-
-/* Called when something that shouldn't happen does */
-void
-#ifdef HAVE_PROTOTYPES
-internal_errorf(int jump, const char *fmt, ...)
-#else
-internal_errorf(jump, fmt, va_alist)
- int jump;
- const char *fmt;
- va_dcl
-#endif
-{
- va_list va;
-
- error_prefix(TRUE);
- shf_fprintf(shl_out, "internal error: ");
- SH_VA_START(va, fmt);
- shf_vfprintf(shl_out, fmt, va);
- va_end(va);
- shf_putchar('\n', shl_out);
- shf_flush(shl_out);
- if (jump)
- unwind(LERROR);
-}
-
-/* used by error reporting functions to print "ksh: .kshrc[25]: " */
-void
-error_prefix(fileline)
- int fileline;
-{
- shf_fprintf(shl_out, "%s: ", kshname + (*kshname == '-'));
- if (fileline && source && source->file != NULL) {
- shf_fprintf(shl_out, "%s[%d]: ", source->file,
- source->errline > 0 ? source->errline : source->line);
- source->errline = 0;
- }
-}
-
-/* printf to shl_out (stderr) with flush */
-void
-#ifdef HAVE_PROTOTYPES
-shellf(const char *fmt, ...)
-#else
-shellf(fmt, va_alist)
- const char *fmt;
- va_dcl
-#endif
-{
- va_list va;
-
- SH_VA_START(va, fmt);
- shf_vfprintf(shl_out, fmt, va);
- va_end(va);
- shf_flush(shl_out);
-}
-
-/* printf to shl_stdout (stdout) */
-void
-#ifdef HAVE_PROTOTYPES
-shprintf(const char *fmt, ...)
-#else
-shprintf(fmt, va_alist)
- const char *fmt;
- va_dcl
-#endif
-{
- va_list va;
-
- if (!shl_stdout_ok)
- internal_errorf(1, "shl_stdout not valid");
- SH_VA_START(va, fmt);
- shf_vfprintf(shl_stdout, fmt, va);
- va_end(va);
-}
-
-/* test if we can seek backwards fd (returns 0 or SHF_UNBUF) */
-int
-can_seek(fd)
- int fd;
-{
- struct stat statb;
-
- return fstat(fd, &statb) == 0 && !S_ISREG(statb.st_mode) ?
- SHF_UNBUF : 0;
-}
-
-struct shf shf_iob[3];
-
-void
-initio()
-{
- shf_fdopen(1, SHF_WR, shl_stdout); /* force buffer allocation */
- shf_fdopen(2, SHF_WR, shl_out);
- shf_fdopen(2, SHF_WR, shl_spare); /* force buffer allocation */
-}
-
-/* A dup2() with error checking */
-int
-ksh_dup2(ofd, nfd, errok)
- int ofd;
- int nfd;
- int errok;
-{
- int ret = dup2(ofd, nfd);
-
- if (ret < 0 && errno != EBADF && !errok)
- errorf("too many files open in shell");
-
-#ifdef DUP2_BROKEN
- /* Ultrix systems like to preserve the close-on-exec flag */
- if (ret >= 0)
- (void) fcntl(nfd, F_SETFD, 0);
-#endif /* DUP2_BROKEN */
-
- return ret;
-}
-
-/*
- * move fd from user space (0<=fd<10) to shell space (fd>=10),
- * set close-on-exec flag.
- */
-int
-savefd(fd, noclose)
- int fd;
- int noclose;
-{
- int nfd;
-
- if (fd < FDBASE) {
- nfd = ksh_dupbase(fd, FDBASE);
- if (nfd < 0)
- if (errno == EBADF)
- return -1;
- else
- errorf("too many files open in shell");
- if (!noclose)
- close(fd);
- } else
- nfd = fd;
- fd_clexec(nfd);
- return nfd;
-}
-
-void
-restfd(fd, ofd)
- int fd, ofd;
-{
- if (fd == 2)
- shf_flush(&shf_iob[fd]);
- if (ofd < 0) /* original fd closed */
- close(fd);
- else {
- ksh_dup2(ofd, fd, TRUE); /* XXX: what to do if this fails? */
- close(ofd);
- }
-}
-
-void
-openpipe(pv)
- register int *pv;
-{
- if (pipe(pv) < 0)
- errorf("can't create pipe - try again");
- pv[0] = savefd(pv[0], 0);
- pv[1] = savefd(pv[1], 0);
-}
-
-void
-closepipe(pv)
- register int *pv;
-{
- close(pv[0]);
- close(pv[1]);
-}
-
-/* Called by iosetup() (deals with 2>&4, etc.), c_read, c_print to turn
- * a string (the X in 2>&X, read -uX, print -uX) into a file descriptor.
- */
-int
-check_fd(name, mode, emsgp)
- char *name;
- int mode;
- const char **emsgp;
-{
- int fd, fl;
-
- if (isdigit(name[0]) && !name[1]) {
- fd = name[0] - '0';
- if ((fl = fcntl(fd = name[0] - '0', F_GETFL, 0)) < 0) {
- if (emsgp)
- *emsgp = "bad file descriptor";
- return -1;
- }
- fl &= O_ACCMODE;
-#ifdef OS2
- if (mode == W_OK ) {
- if (setmode(fd, O_TEXT) == -1) {
- if (emsgp)
- *emsgp = "couldn't set write mode";
- return -1;
- }
- } else if (mode == R_OK)
- if (setmode(fd, O_BINARY) == -1) {
- if (emsgp)
- *emsgp = "couldn't set read mode";
- return -1;
- }
-#else /* OS2 */
- /* X_OK is a kludge to disable this check for dups (x<&1):
- * historical shells never did this check (XXX don't know what
- * posix has to say).
- */
- if (!(mode & X_OK) && fl != O_RDWR
- && (((mode & R_OK) && fl != O_RDONLY)
- || ((mode & W_OK) && fl != O_WRONLY)))
- {
- if (emsgp)
- *emsgp = (fl == O_WRONLY) ?
- "fd not open for reading"
- : "fd not open for writing";
- return -1;
- }
-#endif /* OS2 */
- return fd;
- }
-#ifdef KSH
- else if (name[0] == 'p' && !name[1])
- return coproc_getfd(mode, emsgp);
-#endif /* KSH */
- if (emsgp)
- *emsgp = "illegal file descriptor name";
- return -1;
-}
-
-#ifdef KSH
-/* Called once from main */
-void
-coproc_init()
-{
- coproc.read = coproc.readw = coproc.write = -1;
- coproc.njobs = 0;
- coproc.id = 0;
-}
-
-/* Called by c_read() when eof is read - close fd if it is the co-process fd */
-void
-coproc_read_close(fd)
- int fd;
-{
- if (coproc.read >= 0 && fd == coproc.read) {
- coproc_readw_close(fd);
- close(coproc.read);
- coproc.read = -1;
- }
-}
-
-/* Called by c_read() and by iosetup() to close the other side of the
- * read pipe, so reads will actually terminate.
- */
-void
-coproc_readw_close(fd)
- int fd;
-{
- if (coproc.readw >= 0 && coproc.read >= 0 && fd == coproc.read) {
- close(coproc.readw);
- coproc.readw = -1;
- }
-}
-
-/* Called by c_print when a write to a fd fails with EPIPE and by iosetup
- * when co-process input is dup'd
- */
-void
-coproc_write_close(fd)
- int fd;
-{
- if (coproc.write >= 0 && fd == coproc.write) {
- close(coproc.write);
- coproc.write = -1;
- }
-}
-
-/* Called to check for existance of/value of the co-process file descriptor.
- * (Used by check_fd() and by c_read/c_print to deal with -p option).
- */
-int
-coproc_getfd(mode, emsgp)
- int mode;
- const char **emsgp;
-{
- int fd = (mode & R_OK) ? coproc.read : coproc.write;
-
- if (fd >= 0)
- return fd;
- if (emsgp)
- *emsgp = "no coprocess";
- return -1;
-}
-
-/* called to close file descriptors related to the coprocess (if any)
- * Should be called with SIGCHLD blocked.
- */
-void
-coproc_cleanup(reuse)
- int reuse;
-{
- /* This to allow co-processes to share output pipe */
- if (!reuse || coproc.readw < 0 || coproc.read < 0) {
- if (coproc.read >= 0) {
- close(coproc.read);
- coproc.read = -1;
- }
- if (coproc.readw >= 0) {
- close(coproc.readw);
- coproc.readw = -1;
- }
- }
- if (coproc.write >= 0) {
- close(coproc.write);
- coproc.write = -1;
- }
-}
-#endif /* KSH */
-
-/*
- * temporary files
- */
-
-struct temp *
-maketemp(ap)
- Area *ap;
-{
- static unsigned int inc;
- struct temp *tp;
- int len;
- int fd;
- char *path;
- const char *tmp;
-
- tmp = tmpdir ? tmpdir : "/tmp";
- /* The 20 + 20 is a paranoid worst case for pid/inc */
- len = strlen(tmp) + 3 + 20 + 20 + 1;
- tp = (struct temp *) alloc(sizeof(struct temp) + len, ap);
- tp->name = path = (char *) &tp[1];
- tp->shf = (struct shf *) 0;
- while (1) {
- /* Note that temp files need to fit 8.3 DOS limits */
- shf_snprintf(path, len, "%s/sh%05u.%03x",
- tmp, (unsigned) procpid, inc++);
- /* Mode 0600 to be paranoid, O_TRUNC in case O_EXCL isn't
- * really there.
- */
- fd = open(path, O_RDWR|O_CREAT|O_EXCL|O_TRUNC, 0600);
- if (fd >= 0) {
- tp->shf = shf_fdopen(fd, SHF_WR, (struct shf *) 0);
- break;
- }
- if (errno != EINTR
-#ifdef EEXIST
- && errno != EEXIST
-#endif /* EEXIST */
-#ifdef EISDIR
- && errno != EISDIR
-#endif /* EISDIR */
- )
- /* Error must be printed by called: don't know here if
- * errorf() or bi_errorf() should be used.
- */
- break;
- }
- tp->next = NULL;
- tp->pid = procpid;
- return tp;
-}
diff --git a/bin/pdksh/jobs.c b/bin/pdksh/jobs.c
deleted file mode 100644
index e79f2ac731c..00000000000
--- a/bin/pdksh/jobs.c
+++ /dev/null
@@ -1,1844 +0,0 @@
-/* $OpenBSD: jobs.c,v 1.6 1997/06/19 13:58:43 kstailey Exp $ */
-
-/*
- * Process and job control
- */
-
-/*
- * Reworked/Rewritten version of Eric Gisin's/Ron Natalie's code by
- * Larry Bouzane (larry@cs.mun.ca) and hacked again by
- * Michael Rendell (michael@cs.mun.ca)
- *
- * The interface to the rest of the shell should probably be changed
- * to allow use of vfork() when available but that would be way too much
- * work :)
- *
- * Notes regarding the copious ifdefs:
- * - JOB_SIGS is independent of JOBS - it is defined if there are modern
- * signal and wait routines available. This is prefered, even when
- * JOBS is not defined, since the shell will not otherwise notice when
- * background jobs die until the shell waits for a foreground process
- * to die.
- * - TTY_PGRP defined iff JOBS is defined - defined if there are tty
- * process groups
- * - NEED_PGRP_SYNC defined iff JOBS is defined - see comment below
- */
-
-#include "sh.h"
-#include "ksh_stat.h"
-#include "ksh_wait.h"
-#include "ksh_times.h"
-#include "tty.h"
-
-/* Start of system configuration stuff */
-
-/* We keep CHILD_MAX zombie processes around (exact value isn't critical) */
-#ifndef CHILD_MAX
-# if defined(HAVE_SYSCONF) && defined(_SC_CHILD_MAX)
-# define CHILD_MAX sysconf(_SC_CHILD_MAX)
-# else /* _SC_CHILD_MAX */
-# ifdef _POSIX_CHILD_MAX
-# define CHILD_MAX ((_POSIX_CHILD_MAX) * 2)
-# else /* _POSIX_CHILD_MAX */
-# define CHILD_MAX 20
-# endif /* _POSIX_CHILD_MAX */
-# endif /* _SC_CHILD_MAX */
-#endif /* !CHILD_MAX */
-
-#ifdef JOBS
-# if defined(HAVE_TCSETPGRP) || defined(TIOCSPGRP)
-# define TTY_PGRP
-# endif
-# ifdef BSD_PGRP
-# define setpgid setpgrp
-# define getpgID() getpgrp(0)
-# else
-# define getpgID() getpgrp()
-# endif
-# if defined(TTY_PGRP) && !defined(HAVE_TCSETPGRP)
-int tcsetpgrp ARGS((int fd, pid_t grp));
-int tcgetpgrp ARGS((int fd));
-
-int
-tcsetpgrp(fd, grp)
- int fd;
- pid_t grp;
-{
- return ioctl(fd, TIOCSPGRP, &grp);
-}
-
-int
-tcgetpgrp(fd)
- int fd;
-{
- int r, grp;
-
- if ((r = ioctl(fd, TIOCGPGRP, &grp)) < 0)
- return r;
- return grp;
-}
-# endif /* !HAVE_TCSETPGRP && TIOCSPGRP */
-#else /* JOBS */
-/* These so we can use ifdef xxx instead of if defined(JOBS) && defined(xxx) */
-# undef TTY_PGRP
-# undef NEED_PGRP_SYNC
-#endif /* JOBS */
-
-/* End of system configuration stuff */
-
-
-/* Order important! */
-#define PRUNNING 0
-#define PEXITED 1
-#define PSIGNALLED 2
-#define PSTOPPED 3
-
-typedef struct proc Proc;
-struct proc {
- Proc *next; /* next process in pipeline (if any) */
- int state;
- WAIT_T status; /* wait status */
- pid_t pid; /* process id */
- char command[48]; /* process command string */
-};
-
-/* Notify/print flag - j_print() argument */
-#define JP_NONE 0 /* don't print anything */
-#define JP_SHORT 1 /* print signals processes were killed by */
-#define JP_MEDIUM 2 /* print [job-num] -/+ command */
-#define JP_LONG 3 /* print [job-num] -/+ pid command */
-#define JP_PGRP 4 /* print pgrp */
-
-/* put_job() flags */
-#define PJ_ON_FRONT 0 /* at very front */
-#define PJ_PAST_STOPPED 1 /* just past any stopped jobs */
-
-/* Job.flags values */
-#define JF_STARTED 0x001 /* set when all processes in job are started */
-#define JF_WAITING 0x002 /* set if j_waitj() is waiting on job */
-#define JF_W_ASYNCNOTIFY 0x004 /* set if waiting and async notification ok */
-#define JF_XXCOM 0x008 /* set for `command` jobs */
-#define JF_FG 0x010 /* running in foreground (also has tty pgrp) */
-#define JF_SAVEDTTY 0x020 /* j->ttystate is valid */
-#define JF_CHANGED 0x040 /* process has changed state */
-#define JF_KNOWN 0x080 /* $! referenced */
-#define JF_ZOMBIE 0x100 /* known, unwaited process */
-#define JF_REMOVE 0x200 /* flaged for removal (j_jobs()/j_noityf()) */
-#define JF_USETTYMODE 0x400 /* tty mode saved if process exits normally */
-
-typedef struct job Job;
-struct job {
- Job *next; /* next job in list */
- int job; /* job number: %n */
- int flags; /* see JF_* */
- int state; /* job state */
- int status; /* exit status of last process */
- pid_t pgrp; /* process group of job */
- pid_t ppid; /* pid of process that forked job */
- INT32 age; /* number of jobs started */
- clock_t systime; /* system time used by job */
- clock_t usrtime; /* user time used by job */
- Proc *proc_list; /* process list */
- Proc *last_proc; /* last process in list */
-#ifdef KSH
- Coproc_id coproc_id; /* 0 or id of coprocess output pipe */
-#endif /* KSH */
-#ifdef TTY_PGRP
- TTY_state ttystate; /* saved tty state for stopped jobs */
-#endif /* TTY_PGRP */
-};
-
-/* Flags for j_waitj() */
-#define JW_NONE 0x00
-#define JW_INTERRUPT 0x01 /* ^C will stop the wait */
-#define JW_ASYNCNOTIFY 0x02 /* asynchronous notification during wait ok */
-#define JW_STOPPEDWAIT 0x04 /* wait even if job stopped */
-
-/* Error codes for j_lookup() */
-#define JL_OK 0
-#define JL_NOSUCH 1 /* no such job */
-#define JL_AMBIG 2 /* %foo or %?foo is ambiguous */
-#define JL_INVALID 3 /* non-pid, non-% job id */
-
-static const char *const lookup_msgs[] = {
- null,
- "no such job",
- "ambiguous",
- "argument must be %job or process id",
- (char *) 0
- };
-clock_t j_systime, j_usrtime; /* user and system time of last j_waitjed job */
-
-static Job *job_list; /* job list */
-static Job *last_job;
-static Job *async_job;
-static pid_t async_pid;
-
-static int nzombie; /* # of zombies owned by this process */
-static INT32 njobs; /* # of jobs started */
-static int child_max; /* CHILD_MAX */
-
-
-#ifdef JOB_SIGS
-/* held_sigchld is set if sigchld occurs before a job is completely started */
-static int held_sigchld;
-#endif /* JOB_SIGS */
-
-#ifdef JOBS
-static struct shf *shl_j;
-#endif /* JOBS */
-
-#ifdef NEED_PGRP_SYNC
-/* On some systems, the kernel doesn't count zombie processes when checking
- * if a process group is valid, which can cause problems in creating the
- * pipeline "cmd1 | cmd2": if cmd1 can die (and go into the zombie state)
- * before cmd2 is started, the kernel doesn't allow the setpgid() for cmd2
- * to succeed. Solution is to create a pipe between the parent and the first
- * process; the first process doesn't do anything until the pipe is closed
- * and the parent doesn't close the pipe until all the processes are started.
- */
-static int j_sync_pipe[2];
-static int j_sync_open;
-#endif /* NEED_PGRP_SYNC */
-
-#ifdef TTY_PGRP
-static int ttypgrp_ok; /* set if can use tty pgrps */
-static pid_t restore_ttypgrp = -1;
-static pid_t our_pgrp;
-static int const tt_sigs[] = { SIGTSTP, SIGTTIN, SIGTTOU };
-#endif /* TTY_PGRP */
-
-static void j_set_async ARGS((Job *j));
-static void j_startjob ARGS((Job *j));
-static int j_waitj ARGS((Job *j, int flags, const char *where));
-static RETSIGTYPE j_sigchld ARGS((int sig));
-static void j_print ARGS((Job *j, int how, struct shf *shf));
-static Job *j_lookup ARGS((const char *cp, int *ecodep));
-static Job *new_job ARGS((void));
-static Proc *new_proc ARGS((void));
-static void check_job ARGS((Job *j));
-static void put_job ARGS((Job *j, int where));
-static void remove_job ARGS((Job *j, const char *where));
-static void kill_job ARGS((Job *j));
-static void fill_command ARGS((char *c, int len, struct op *t));
-
-/* initialize job control */
-void
-j_init(mflagset)
- int mflagset;
-{
- child_max = CHILD_MAX; /* so syscon() isn't always being called */
-
-#ifdef JOB_SIGS
- sigemptyset(&sm_default);
- sigprocmask(SIG_SETMASK, &sm_default, (sigset_t *) 0);
-
- sigemptyset(&sm_sigchld);
- sigaddset(&sm_sigchld, SIGCHLD);
-
- setsig(&sigtraps[SIGCHLD], j_sigchld,
- SS_RESTORE_ORIG|SS_FORCE|SS_SHTRAP);
-#else /* JOB_SIGS */
- /* Make sure SIGCHLD isn't ignored - can do odd things under SYSV */
- setsig(&sigtraps[SIGCHLD], SIG_DFL, SS_RESTORE_ORIG|SS_FORCE);
-#endif /* JOB_SIGS */
-
-#ifdef JOBS
- if (!mflagset && Flag(FTALKING))
- Flag(FMONITOR) = 1;
-
- /* shl_j is used to do asynchronous notification (used in
- * an interrupt handler, so need a distinct shf)
- */
- shl_j = shf_fdopen(2, SHF_WR, (struct shf *) 0);
-
-# ifdef TTY_PGRP
- if (Flag(FMONITOR) || Flag(FTALKING)) {
- int i;
-
- /* the TF_SHELL_USES test is a kludge that lets us know if
- * if the signals have been changed by the shell.
- */
- for (i = NELEM(tt_sigs); --i >= 0; ) {
- sigtraps[tt_sigs[i]].flags |= TF_SHELL_USES;
- /* j_change() sets this to SS_RESTORE_DFL if FMONITOR */
- setsig(&sigtraps[tt_sigs[i]], SIG_IGN,
- SS_RESTORE_IGN|SS_FORCE);
- }
- }
-# endif /* TTY_PGRP */
-
- /* j_change() calls tty_init() */
- if (Flag(FMONITOR))
- j_change();
- else
-#endif /* JOBS */
- if (Flag(FTALKING))
- tty_init(TRUE);
-}
-
-/* job cleanup before shell exit */
-void
-j_exit()
-{
- /* kill stopped, and possibly running, jobs */
- Job *j;
- int killed = 0;
-
- for (j = job_list; j != (Job *) 0; j = j->next) {
- if (j->ppid == procpid
- && (j->state == PSTOPPED
- || (j->state == PRUNNING
- && ((j->flags & JF_FG)
- || (Flag(FLOGIN) && !Flag(FNOHUP)
- && procpid == kshpid)))))
- {
- killed = 1;
- killpg(j->pgrp, SIGHUP);
-#ifdef JOBS
- if (j->state == PSTOPPED)
- killpg(j->pgrp, SIGCONT);
-#endif /* JOBS */
- }
- }
- if (killed)
- sleep(1);
- j_notify();
-
-#ifdef JOBS
-# ifdef TTY_PGRP
- if (kshpid == procpid && restore_ttypgrp >= 0) {
- /* Need to restore the tty pgrp to what it was when the
- * shell started up, so that the process that started us
- * will be able to access the tty when we are done.
- * Also need to restore our process group in case we are
- * about to do an exec so that both our parent and the
- * process we are to become will be able to access the tty.
- */
- tcsetpgrp(tty_fd, restore_ttypgrp);
- setpgid(0, restore_ttypgrp);
- }
-# endif /* TTY_PGRP */
- if (Flag(FMONITOR)) {
- Flag(FMONITOR) = 0;
- j_change();
- }
-#endif /* JOBS */
-}
-
-#ifdef JOBS
-/* turn job control on or off according to Flag(FMONITOR) */
-void
-j_change()
-{
- int i;
-
- if (Flag(FMONITOR)) {
- /* Don't call get_tty() 'til we own the tty process group */
- tty_init(FALSE);
-
-# ifdef TTY_PGRP
- /* no controlling tty, no SIGT* */
- ttypgrp_ok = tty_fd >= 0 && tty_devtty;
-
- if (ttypgrp_ok && (our_pgrp = getpgID()) < 0) {
- warningf(FALSE, "j_init: getpgrp() failed: %s",
- strerror(errno));
- ttypgrp_ok = 0;
- }
- if (ttypgrp_ok) {
- setsig(&sigtraps[SIGTTIN], SIG_DFL,
- SS_RESTORE_ORIG|SS_FORCE);
- /* wait to be given tty (POSIX.1, B.2, job control) */
- while (1) {
- pid_t ttypgrp;
-
- if ((ttypgrp = tcgetpgrp(tty_fd)) < 0) {
- warningf(FALSE,
- "j_init: tcgetpgrp() failed: %s",
- strerror(errno));
- ttypgrp_ok = 0;
- break;
- }
- if (ttypgrp == our_pgrp)
- break;
- kill(0, SIGTTIN);
- }
- }
- for (i = NELEM(tt_sigs); --i >= 0; )
- setsig(&sigtraps[tt_sigs[i]], SIG_IGN,
- SS_RESTORE_DFL|SS_FORCE);
- if (ttypgrp_ok && our_pgrp != kshpid) {
- if (setpgid(0, kshpid) < 0) {
- warningf(FALSE,
- "j_init: setpgid() failed: %s",
- strerror(errno));
- ttypgrp_ok = 0;
- } else {
- if (tcsetpgrp(tty_fd, kshpid) < 0) {
- warningf(FALSE,
- "j_init: tcsetpgrp() failed: %s",
- strerror(errno));
- ttypgrp_ok = 0;
- } else
- restore_ttypgrp = our_pgrp;
- our_pgrp = kshpid;
- }
- }
-# if defined(NTTYDISC) && defined(TIOCSETD) && !defined(HAVE_TERMIOS_H) && !defined(HAVE_TERMIO_H)
- if (ttypgrp_ok) {
- int ldisc = NTTYDISC;
-
- if (ioctl(tty_fd, TIOCSETD, &ldisc) < 0)
- warningf(FALSE,
- "j_init: can't set new line discipline: %s",
- strerror(errno));
- }
-# endif /* NTTYDISC && TIOCSETD */
- if (!ttypgrp_ok)
- warningf(FALSE, "warning: won't have full job control");
-# endif /* TTY_PGRP */
- if (tty_fd >= 0)
- get_tty(tty_fd, &tty_state);
- } else {
-# ifdef TTY_PGRP
- ttypgrp_ok = 0;
- if (Flag(FTALKING))
- for (i = NELEM(tt_sigs); --i >= 0; )
- setsig(&sigtraps[tt_sigs[i]], SIG_IGN,
- SS_RESTORE_IGN|SS_FORCE);
- else
- for (i = NELEM(tt_sigs); --i >= 0; ) {
- if (sigtraps[tt_sigs[i]].flags & (TF_ORIG_IGN
- |TF_ORIG_DFL))
- setsig(&sigtraps[tt_sigs[i]],
- (sigtraps[tt_sigs[i]].flags & TF_ORIG_IGN) ? SIG_IGN : SIG_DFL,
- SS_RESTORE_ORIG|SS_FORCE);
- }
-# endif /* TTY_PGRP */
- if (!Flag(FTALKING))
- tty_close();
- }
-}
-#endif /* JOBS */
-
-/* execute tree in child subprocess */
-int
-exchild(t, flags, close_fd)
- struct op *t;
- int flags;
- int close_fd; /* used if XPCLOSE or XCCLOSE */
-{
- static Proc *last_proc; /* for pipelines */
-
- int i;
-#ifdef JOB_SIGS
- sigset_t omask;
-#endif /* JOB_SIGS */
- Proc *p;
- Job *j;
- int rv = 0;
- int forksleep;
- int orig_flags = flags;
- int ischild;
-
- flags &= ~(XFORK|XPCLOSE|XCCLOSE|XCOPROC);
- if (flags & XEXEC)
- return execute(t, flags);
-
-#ifdef JOB_SIGS
- /* no SIGCHLD's while messing with job and process lists */
- sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
-#endif /* JOB_SIGS */
-
- p = new_proc();
- p->next = (Proc *) 0;
- p->state = PRUNNING;
- WSTATUS(p->status) = 0;
- p->pid = 0;
-
- /* link process into jobs list */
- if (flags&XPIPEI) { /* continuing with a pipe */
- j = last_job;
- last_proc->next = p;
- last_proc = p;
- } else {
-#ifdef NEED_PGRP_SYNC
- if (j_sync_open) { /* should never happen */
- j_sync_open = 0;
- closepipe(j_sync_pipe);
- }
- /* don't do the sync pipe business if there is no pipeline */
- if (flags & XPIPEO) {
- openpipe(j_sync_pipe);
- j_sync_open = 1;
- }
-#endif /* NEED_PGRP_SYNC */
- j = new_job(); /* fills in j->job */
- /* we don't consider XXCOM's foreground since they don't get
- * tty process group and we don't save or restore tty modes.
- */
- j->flags = (flags & XXCOM) ? JF_XXCOM
- : ((flags & XBGND) ? 0 : (JF_FG|JF_USETTYMODE));
- j->usrtime = j->systime = 0;
- j->state = PRUNNING;
- j->pgrp = 0;
- j->ppid = procpid;
- j->age = ++njobs;
- j->proc_list = p;
-#ifdef KSH
- j->coproc_id = 0;
-#endif /* KSH */
- last_job = j;
- last_proc = p;
- put_job(j, PJ_PAST_STOPPED);
- }
-
- fill_command(p->command, sizeof(p->command), t);
-
- /* create child process */
- forksleep = 1;
- while ((i = fork()) < 0 && errno == EAGAIN && forksleep < 32) {
- if (intrsig) /* allow user to ^C out... */
- break;
- sleep(forksleep);
- forksleep <<= 1;
- }
- if (i < 0) {
- kill_job(j);
- remove_job(j, "fork failed");
-#ifdef NEED_PGRP_SYNC
- if (j_sync_open) {
- closepipe(j_sync_pipe);
- j_sync_open = 0;
- }
-#endif /* NEED_PGRP_SYNC */
-#ifdef JOB_SIGS
- sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0);
-#endif /* JOB_SIGS */
- errorf("cannot fork - try again");
- }
- ischild = i == 0;
- if (ischild)
- p->pid = procpid = getpid();
- else
- p->pid = i;
-
-#ifdef JOBS
- /* job control set up */
- if (Flag(FMONITOR) && !(flags&XXCOM)) {
- int dotty = 0;
-# ifdef NEED_PGRP_SYNC
- int first_child_sync = 0;
-# endif /* NEED_PGRP_SYNC */
-
-# ifdef NEED_PGRP_SYNC
- if (j_sync_open) {
- /*
- * The Parent closes 0, keeps 1 open 'til the whole
- * pipeline is started. The First child closes 1,
- * keeps 0 open (reads from it). The remaining
- * children just have to close 1 (parent has already
- * closeed 0).
- */
- if (j->pgrp == 0) { /* First process */
- close(j_sync_pipe[ischild]);
- j_sync_pipe[ischild] = -1;
- first_child_sync = ischild;
- } else if (ischild) {
- j_sync_open = 0;
- closepipe(j_sync_pipe);
- }
- }
-# endif /* NEED_PGRP_SYNC */
- if (j->pgrp == 0) { /* First process */
- j->pgrp = p->pid;
- dotty = 1;
- }
-
- /* set pgrp in both parent and child to deal with race
- * condition
- */
- setpgid(p->pid, j->pgrp);
-# ifdef TTY_PGRP
- /* YYY: should this be
- if (ttypgrp_ok && ischild && !(flags&XBGND))
- tcsetpgrp(tty_fd, j->pgrp);
- instead? (see also YYY below)
- */
- if (ttypgrp_ok && dotty && !(flags & XBGND))
- tcsetpgrp(tty_fd, j->pgrp);
-# endif /* TTY_PGRP */
-# ifdef NEED_PGRP_SYNC
- if (first_child_sync) {
- char c;
- while (read(j_sync_pipe[0], &c, 1) == -1
- && errno == EINTR)
- ;
- close(j_sync_pipe[0]);
- j_sync_open = 0;
- }
-# endif /* NEED_PGRP_SYNC */
- }
-#endif /* JOBS */
-
- /* used to close pipe input fd */
- if (close_fd >= 0 && (((orig_flags & XPCLOSE) && !ischild)
- || ((orig_flags & XCCLOSE) && ischild)))
- close(close_fd);
- if (ischild) { /* child */
-#ifdef KSH
- /* Do this before restoring signal */
- if (orig_flags & XCOPROC)
- coproc_cleanup(FALSE);
-#endif /* KSH */
-#ifdef JOB_SIGS
- sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0);
-#endif /* JOB_SIGS */
- cleanup_parents_env();
-#ifdef TTY_PGRP
- /* If FMONITOR or FTALKING is set, these signals are ignored,
- * if neither FMONITOR nor FTALKING are set, the signals have
- * their inherited values.
- */
- if (Flag(FMONITOR) && !(flags & XXCOM)) {
- for (i = NELEM(tt_sigs); --i >= 0; )
- setsig(&sigtraps[tt_sigs[i]], SIG_DFL,
- SS_RESTORE_DFL|SS_FORCE);
- }
-#endif /* TTY_PGRP */
-#ifdef HAVE_NICE
- if (Flag(FBGNICE) && (flags & XBGND))
- nice(4);
-#endif /* HAVE_NICE */
- if ((flags & XBGND) && !Flag(FMONITOR)) {
- setsig(&sigtraps[SIGINT], SIG_IGN,
- SS_RESTORE_IGN|SS_FORCE);
- setsig(&sigtraps[SIGQUIT], SIG_IGN,
- SS_RESTORE_IGN|SS_FORCE);
- if (!(orig_flags & (XPIPEI | XCOPROC))) {
- int fd = open("/dev/null", 0);
- (void) ksh_dup2(fd, 0, TRUE);
- close(fd);
- }
- }
- remove_job(j, "child"); /* in case of `jobs` command */
- nzombie = 0;
-#ifdef JOBS
- ttypgrp_ok = 0;
- Flag(FMONITOR) = 0;
-#endif /* JOBS */
- Flag(FTALKING) = 0;
- tty_close();
- cleartraps();
- execute(t, flags|XEXEC); /* no return */
- internal_errorf(0, "exchild: execute() returned");
- unwind(LLEAVE);
- /* NOTREACHED */
- }
-
- /* shell (parent) stuff */
- if (!(flags & XPIPEO)) { /* last process in a job */
-#ifdef TTY_PGRP
- /* YYY: Is this needed? (see also YYY above)
- if (Flag(FMONITOR) && !(flags&(XXCOM|XBGND)))
- tcsetpgrp(tty_fd, j->pgrp);
- */
-#endif /* TTY_PGRP */
- j_startjob(j);
-#ifdef KSH
- if (orig_flags & XCOPROC) {
- j->coproc_id = coproc.id;
- coproc.njobs++; /* n jobs using co-process output */
- coproc.job = (void *) j; /* j using co-process input */
- }
-#endif /* KSH */
- if (flags & XBGND) {
- j_set_async(j);
- if (Flag(FTALKING)) {
- shf_fprintf(shl_out, "[%d]", j->job);
- for (p = j->proc_list; p; p = p->next)
- shf_fprintf(shl_out, " %d", p->pid);
- shf_putchar('\n', shl_out);
- shf_flush(shl_out);
- }
- } else
- rv = j_waitj(j, JW_NONE, "jw:last proc");
- }
-
-#ifdef JOB_SIGS
- sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0);
-#endif /* JOB_SIGS */
-
- return rv;
-}
-
-/* start the last job: only used for `command` jobs */
-void
-startlast()
-{
-#ifdef JOB_SIGS
- sigset_t omask;
-
- sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
-#endif /* JOB_SIGS */
-
- if (last_job) { /* no need to report error - waitlast() will do it */
- /* ensure it isn't removed by check_job() */
- last_job->flags |= JF_WAITING;
- j_startjob(last_job);
- }
-#ifdef JOB_SIGS
- sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0);
-#endif /* JOB_SIGS */
-}
-
-/* wait for last job: only used for `command` jobs */
-int
-waitlast()
-{
- int rv;
- Job *j;
-#ifdef JOB_SIGS
- sigset_t omask;
-
- sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
-#endif /* JOB_SIGS */
-
- j = last_job;
- if (!j || !(j->flags & JF_STARTED)) {
- if (!j)
- warningf(TRUE, "waitlast: no last job");
- else
- internal_errorf(0, "waitlast: not started");
-#ifdef JOB_SIGS
- sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0);
-#endif /* JOB_SIGS */
- return 125; /* not so arbitrary, non-zero value */
- }
-
- rv = j_waitj(j, JW_NONE, "jw:waitlast");
-
-#ifdef JOB_SIGS
- sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0);
-#endif /* JOB_SIGS */
-
- return rv;
-}
-
-/* wait for child, interruptable. */
-int
-waitfor(cp, sigp)
- const char *cp;
- int *sigp;
-{
- int rv;
- Job *j;
- int ecode;
- int flags = JW_INTERRUPT|JW_ASYNCNOTIFY;
-#ifdef JOB_SIGS
- sigset_t omask;
-
- sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
-#endif /* JOB_SIGS */
-
- *sigp = 0;
-
- if (cp == (char *) 0) {
- /* wait for an unspecified job - always returns 0, so
- * don't have to worry about exited/signaled jobs
- */
- for (j = job_list; j; j = j->next)
- /* at&t ksh will wait for stopped jobs - we don't */
- if (j->ppid == procpid && j->state == PRUNNING)
- break;
- if (!j) {
-#ifdef JOB_SIGS
- sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0);
-#endif /* JOB_SIGS */
- return -1;
- }
- } else if ((j = j_lookup(cp, &ecode))) {
- /* don't report normal job completion */
- flags &= ~JW_ASYNCNOTIFY;
- if (j->ppid != procpid) {
-#ifdef JOB_SIGS
- sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0);
-#endif /* JOB_SIGS */
- return -1;
- }
- } else {
-#ifdef JOB_SIGS
- sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0);
-#endif /* JOB_SIGS */
- if (ecode == JL_NOSUCH)
- return -1;
- bi_errorf("%s: %s", cp, lookup_msgs[ecode]);
- }
-
- /* at&t ksh will wait for stopped jobs - we don't */
- rv = j_waitj(j, flags, "jw:waitfor");
-
-#ifdef JOB_SIGS
- sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0);
-#endif /* JOB_SIGS */
-
- if (rv < 0) /* we were interrupted */
- *sigp = 128 + -rv;
-
- return rv;
-}
-
-/* kill (built-in) a job */
-int
-j_kill(cp, sig)
- const char *cp;
- int sig;
-{
- Job *j;
- Proc *p;
- int rv = 0;
- int ecode;
-#ifdef JOB_SIGS
- sigset_t omask;
-
- sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
-#endif /* JOB_SIGS */
-
- if ((j = j_lookup(cp, &ecode)) == (Job *) 0) {
-#ifdef JOB_SIGS
- sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0);
-#endif /* JOB_SIGS */
- bi_errorf("%s: %s", cp, lookup_msgs[ecode]);
- return 1;
- }
-
- if (j->pgrp == 0) { /* started when !Flag(FMONITOR) */
- for (p=j->proc_list; p != (Proc *) 0; p = p->next)
- if (kill(p->pid, sig) < 0) {
- bi_errorf("%s: %s", cp, strerror(errno));
- rv = 1;
- }
- } else {
-#ifdef JOBS
- if (j->state == PSTOPPED && (sig == SIGTERM || sig == SIGHUP))
- (void) killpg(j->pgrp, SIGCONT);
-#endif /* JOBS */
- if (killpg(j->pgrp, sig) < 0) {
- bi_errorf("%s: %s", cp, strerror(errno));
- rv = 1;
- }
- }
-
-#ifdef JOB_SIGS
- sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0);
-#endif /* JOB_SIGS */
-
- return rv;
-}
-
-#ifdef JOBS
-/* fg and bg built-ins: called only if Flag(FMONITOR) set */
-int
-j_resume(cp, bg)
- const char *cp;
- int bg;
-{
- Job *j;
- Proc *p;
- int ecode;
- int running;
- int rv = 0;
- sigset_t omask;
-
- sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
-
- if ((j = j_lookup(cp, &ecode)) == (Job *) 0) {
- sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0);
- bi_errorf("%s: %s", cp, lookup_msgs[ecode]);
- return 1;
- }
-
- if (j->pgrp == 0) {
- sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0);
- bi_errorf("job not job-controlled");
- return 1;
- }
-
- if (bg)
- shprintf("[%d] ", j->job);
-
- running = 0;
- for (p = j->proc_list; p != (Proc *) 0; p = p->next) {
- if (p->state == PSTOPPED) {
- p->state = PRUNNING;
- WSTATUS(p->status) = 0;
- running = 1;
- }
- shprintf("%s%s", p->command, p->next ? "| " : null);
- }
- shprintf(newline);
- shf_flush(shl_stdout);
- if (running)
- j->state = PRUNNING;
-
- put_job(j, PJ_PAST_STOPPED);
- if (bg)
- j_set_async(j);
- else {
-# ifdef TTY_PGRP
- /* attach tty to job */
- if (j->state == PRUNNING) {
- if (ttypgrp_ok && (j->flags & JF_SAVEDTTY)) {
- set_tty(tty_fd, &j->ttystate, TF_NONE);
- }
- if (ttypgrp_ok && tcsetpgrp(tty_fd, j->pgrp) < 0) {
- if (j->flags & JF_SAVEDTTY)
- set_tty(tty_fd, &tty_state, TF_NONE);
- sigprocmask(SIG_SETMASK, &omask,
- (sigset_t *) 0);
- bi_errorf("1st tcsetpgrp(%d, %d) failed: %s",
- tty_fd, (int) j->pgrp, strerror(errno));
- return 1;
- }
- }
-# endif /* TTY_PGRP */
- j->flags |= JF_FG;
- j->flags &= ~JF_KNOWN;
- if (j == async_job)
- async_job = (Job *) 0;
- }
-
- if (j->state == PRUNNING && killpg(j->pgrp, SIGCONT) < 0) {
- int err = errno;
-
- if (!bg) {
- j->flags &= ~JF_FG;
-# ifdef TTY_PGRP
- if (ttypgrp_ok && (j->flags & JF_SAVEDTTY))
- set_tty(tty_fd, &tty_state, TF_NONE);
- if (ttypgrp_ok && tcsetpgrp(tty_fd, our_pgrp) < 0) {
- warningf(TRUE,
- "fg: 2nd tcsetpgrp(%d, %d) failed: %s",
- tty_fd, (int) our_pgrp,
- strerror(errno));
- }
-# endif /* TTY_PGRP */
- }
- sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0);
- bi_errorf("cannot continue job %s: %s",
- cp, strerror(err));
- return 1;
- }
- if (!bg) {
-# ifdef TTY_PGRP
- if (ttypgrp_ok) {
- j->flags &= ~JF_SAVEDTTY;
- }
-# endif /* TTY_PGRP */
- rv = j_waitj(j, JW_NONE, "jw:resume");
- }
- sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0);
- return rv;
-}
-#endif /* JOBS */
-
-/* are there any running or stopped jobs ? */
-int
-j_stopped_running()
-{
- Job *j;
- int which = 0;
-
- for (j = job_list; j != (Job *) 0; j = j->next) {
-#ifdef JOBS
- if (j->ppid == procpid && j->state == PSTOPPED)
- which |= 1;
-#endif /* JOBS */
- if (Flag(FLOGIN) && !Flag(FNOHUP) && procpid == kshpid
- && j->ppid == procpid && j->state == PRUNNING)
- which |= 2;
- }
- if (which) {
- shellf("You have %s%s%s jobs\n",
- which & 1 ? "stopped" : "",
- which == 3 ? " and " : "",
- which & 2 ? "running" : "");
- return 1;
- }
-
- return 0;
-}
-
-/* list jobs for jobs built-in */
-int
-j_jobs(cp, slp, nflag)
- const char *cp;
- int slp; /* 0: short, 1: long, 2: pgrp */
- int nflag;
-{
- Job *j, *tmp;
- int how;
- int zflag = 0;
-#ifdef JOB_SIGS
- sigset_t omask;
-
- sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
-#endif /* JOB_SIGS */
-
- if (nflag < 0) { /* kludge: print zombies */
- nflag = 0;
- zflag = 1;
- }
- if (cp) {
- int ecode;
-
- if ((j = j_lookup(cp, &ecode)) == (Job *) 0) {
-#ifdef JOB_SIGS
- sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0);
-#endif /* JOB_SIGS */
- bi_errorf("%s: %s", cp, lookup_msgs[ecode]);
- return 1;
- }
- } else
- j = job_list;
- how = slp == 0 ? JP_MEDIUM : (slp == 1 ? JP_LONG : JP_PGRP);
- for (; j; j = j->next) {
- if ((!(j->flags & JF_ZOMBIE) || zflag)
- && (!nflag || (j->flags & JF_CHANGED)))
- {
- j_print(j, how, shl_stdout);
- if (j->state == PEXITED || j->state == PSIGNALLED)
- j->flags |= JF_REMOVE;
- }
- if (cp)
- break;
- }
- /* Remove jobs after printing so there won't be multiple + or - jobs */
- for (j = job_list; j; j = tmp) {
- tmp = j->next;
- if (j->flags & JF_REMOVE)
- remove_job(j, "jobs");
- }
-#ifdef JOB_SIGS
- sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0);
-#endif /* JOB_SIGS */
- return 0;
-}
-
-/* list jobs for top-level notification */
-void
-j_notify()
-{
- Job *j, *tmp;
-#ifdef JOB_SIGS
- sigset_t omask;
-
- sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
-#endif /* JOB_SIGS */
- for (j = job_list; j; j = j->next) {
-#ifdef JOBS
- if (Flag(FMONITOR) && (j->flags & JF_CHANGED))
- j_print(j, JP_MEDIUM, shl_out);
-#endif /* JOBS */
- /* Remove job after doing reports so there aren't
- * multiple +/- jobs.
- */
- if (j->state == PEXITED || j->state == PSIGNALLED)
- j->flags |= JF_REMOVE;
- }
- for (j = job_list; j; j = tmp) {
- tmp = j->next;
- if (j->flags & JF_REMOVE)
- remove_job(j, "notify");
- }
- shf_flush(shl_out);
-#ifdef JOB_SIGS
- sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0);
-#endif /* JOB_SIGS */
-}
-
-/* Return pid of last process in last asynchornous job */
-pid_t
-j_async()
-{
-#ifdef JOB_SIGS
- sigset_t omask;
-
- sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
-#endif /* JOB_SIGS */
-
- if (async_job)
- async_job->flags |= JF_KNOWN;
-
-#ifdef JOB_SIGS
- sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0);
-#endif /* JOB_SIGS */
-
- return async_pid;
-}
-
-/* Make j the last async process
- *
- * If jobs are compiled in then this routine expects sigchld to be blocked.
- */
-static void
-j_set_async(j)
- Job *j;
-{
- Job *jl, *oldest;
-
- if (async_job && (async_job->flags & (JF_KNOWN|JF_ZOMBIE)) == JF_ZOMBIE)
- remove_job(async_job, "async");
- if (!(j->flags & JF_STARTED)) {
- internal_errorf(0, "j_async: job not started");
- return;
- }
- async_job = j;
- async_pid = j->last_proc->pid;
- while (nzombie > child_max) {
- oldest = (Job *) 0;
- for (jl = job_list; jl; jl = jl->next)
- if (jl != async_job && (jl->flags & JF_ZOMBIE)
- && (!oldest || jl->age < oldest->age))
- oldest = jl;
- if (!oldest) {
- /* XXX debugging */
- if (!(async_job->flags & JF_ZOMBIE) || nzombie != 1) {
- internal_errorf(0, "j_async: bad nzombie (%d)", nzombie);
- nzombie = 0;
- }
- break;
- }
- remove_job(oldest, "zombie");
- }
-}
-
-/* Start a job: set STARTED, check for held signals and set j->last_proc
- *
- * If jobs are compiled in then this routine expects sigchld to be blocked.
- */
-static void
-j_startjob(j)
- Job *j;
-{
- Proc *p;
-
- j->flags |= JF_STARTED;
- for (p = j->proc_list; p->next; p = p->next)
- ;
- j->last_proc = p;
-
-#ifdef NEED_PGRP_SYNC
- if (j_sync_open) {
- j_sync_open = 0;
- closepipe(j_sync_pipe);
- }
-#endif /* NEED_PGRP_SYNC */
-#ifdef JOB_SIGS
- if (held_sigchld) {
- held_sigchld = 0;
- /* Don't call j_sigchld() as it may remove job... */
- kill(procpid, SIGCHLD);
- }
-#endif /* JOB_SIGS */
-}
-
-/*
- * wait for job to complete or change state
- *
- * If jobs are compiled in then this routine expects sigchld to be blocked.
- */
-static int
-j_waitj(j, flags, where)
- Job *j;
- int flags; /* see JW_* */
- const char *where;
-{
- int rv;
-
- /*
- * No auto-notify on the job we are waiting on.
- */
- j->flags |= JF_WAITING;
- if (flags & JW_ASYNCNOTIFY)
- j->flags |= JF_W_ASYNCNOTIFY;
-
- if (!Flag(FMONITOR))
- flags |= JW_STOPPEDWAIT;
-
- while ((volatile int) j->state == PRUNNING
- || ((flags & JW_STOPPEDWAIT)
- && (volatile int) j->state == PSTOPPED))
- {
-#ifdef JOB_SIGS
- sigsuspend(&sm_default);
-#else /* JOB_SIGS */
- j_sigchld(SIGCHLD);
-#endif /* JOB_SIGS */
- if (fatal_trap) {
- int oldf = j->flags & (JF_WAITING|JF_W_ASYNCNOTIFY);
- j->flags &= ~(JF_WAITING|JF_W_ASYNCNOTIFY);
- runtraps(TF_FATAL);
- j->flags |= oldf; /* not reached... */
- }
- if ((flags & JW_INTERRUPT) && (rv = trap_pending())) {
- j->flags &= ~(JF_WAITING|JF_W_ASYNCNOTIFY);
- return -rv;
- }
- }
- j->flags &= ~(JF_WAITING|JF_W_ASYNCNOTIFY);
-
- if (j->flags & JF_FG) {
- WAIT_T status;
-
- j->flags &= ~JF_FG;
-#ifdef TTY_PGRP
- if (Flag(FMONITOR) && ttypgrp_ok && j->pgrp) {
- if (tcsetpgrp(tty_fd, our_pgrp) < 0) {
- warningf(TRUE,
- "j_waitj: tcsetpgrp(%d, %d) failed: %s",
- tty_fd, (int) our_pgrp,
- strerror(errno));
- }
- if (j->state == PSTOPPED) {
- j->flags |= JF_SAVEDTTY;
- get_tty(tty_fd, &j->ttystate);
- }
- }
-#endif /* TTY_PGRP */
- if (tty_fd >= 0) {
- /* Only restore tty settings if job was originally
- * started in the foreground. Problems can be
- * caused by things like `more foobar &' which will
- * typically get and save the shell's vi/emacs tty
- * settings before setting up the tty for itself;
- * when more exits, it restores the `original'
- * settings, and things go down hill from there...
- */
- if (j->state == PEXITED && j->status == 0
- && (j->flags & JF_USETTYMODE))
- {
- get_tty(tty_fd, &tty_state);
- } else {
- set_tty(tty_fd, &tty_state,
- (j->state == PEXITED) ? 0 : TF_MIPSKLUDGE);
- /* Don't use tty mode if job is stopped and
- * later restarted and exits. Consider
- * the sequence:
- * vi foo (stopped)
- * ...
- * stty something
- * ...
- * fg (vi; ZZ)
- * mode should be that of the stty, not what
- * was before the vi started.
- */
- if (j->state == PSTOPPED)
- j->flags &= ~JF_USETTYMODE;
- }
- }
-#ifdef JOBS
- /* If it looks like user hit ^C to kill a job, pretend we got
- * one too to break out of for loops, etc. (at&t ksh does this
- * even when not monitoring, but this doesn't make sense since
- * a tty generated ^C goes to the whole process group)
- */
- status = j->last_proc->status;
- if (Flag(FMONITOR) && j->state == PSIGNALLED
- && WIFSIGNALED(status)
- && (sigtraps[WTERMSIG(status)].flags & TF_TTY_INTR))
- trapsig(WTERMSIG(status));
-#endif /* JOBS */
- }
-
- j_usrtime = j->usrtime;
- j_systime = j->systime;
- rv = j->status;
-
- if (!(flags & JW_ASYNCNOTIFY)
- && (!Flag(FMONITOR) || j->state != PSTOPPED))
- {
- j_print(j, JP_SHORT, shl_out);
- shf_flush(shl_out);
- }
- if (j->state != PSTOPPED
- && (!Flag(FMONITOR) || !(flags & JW_ASYNCNOTIFY)))
- remove_job(j, where);
-
- return rv;
-}
-
-/* SIGCHLD handler to reap children and update job states
- *
- * If jobs are compiled in then this routine expects sigchld to be blocked.
- */
-static RETSIGTYPE
-j_sigchld(sig)
- int sig;
-{
- int errno_ = errno;
- Job *j;
- Proc UNINITIALIZED(*p);
- int pid;
- WAIT_T status;
- struct tms t0, t1;
-
-#ifdef JOB_SIGS
- /* Don't wait for any processes if a job is partially started.
- * This is so we don't do away with the process group leader
- * before all the processes in a pipe line are started (so the
- * setpgid() won't fail)
- */
- for (j = job_list; j; j = j->next)
- if (j->ppid == procpid && !(j->flags & JF_STARTED)) {
- held_sigchld = 1;
- return RETSIGVAL;
- }
-#endif /* JOB_SIGS */
-
- ksh_times(&t0);
- do {
-#ifdef JOB_SIGS
- pid = ksh_waitpid(-1, &status, (WNOHANG|WUNTRACED));
-#else /* JOB_SIGS */
- pid = wait(&status);
-#endif /* JOB_SIGS */
-
- if (pid <= 0) /* return if would block (0) ... */
- break; /* ... or no children or interrupted (-1) */
-
- ksh_times(&t1);
-
- /* find job and process structures for this pid */
- for (j = job_list; j != (Job *) 0; j = j->next)
- for (p = j->proc_list; p != (Proc *) 0; p = p->next)
- if (p->pid == pid)
- goto found;
-found:
- if (j == (Job *) 0) {
- /* Can occur if process has kids, then execs shell
- warningf(TRUE, "bad process waited for (pid = %d)",
- pid);
- */
- t0 = t1;
- continue;
- }
-
- j->usrtime += t1.tms_cutime - t0.tms_cutime;
- j->systime += t1.tms_cstime - t0.tms_cstime;
- t0 = t1;
- p->status = status;
-#ifdef JOBS
- if (WIFSTOPPED(status))
- p->state = PSTOPPED;
- else
-#endif /* JOBS */
- if (WIFSIGNALED(status))
- p->state = PSIGNALLED;
- else
- p->state = PEXITED;
-
- check_job(j); /* check to see if entire job is done */
- }
-#ifdef JOB_SIGS
- while (1);
-#else /* JOB_SIGS */
- while (0);
-#endif /* JOB_SIGS */
-
- errno = errno_;
-
- return RETSIGVAL;
-}
-
-/*
- * Called only when a process in j has exited/stopped (ie, called only
- * from j_sigchld()). If no processes are running, the job status
- * and state are updated, asynchronous job notification is done and,
- * if unneeded, the job is removed.
- *
- * If jobs are compiled in then this routine expects sigchld to be blocked.
- */
-static void
-check_job(j)
- Job *j;
-{
- int jstate;
- Proc *p;
-
- /* XXX debugging (nasty - interrupt routine using shl_out) */
- if (!(j->flags & JF_STARTED)) {
- internal_errorf(0, "check_job: job started (flags 0x%x)",
- j->flags);
- return;
- }
-
- jstate = PRUNNING;
- for (p=j->proc_list; p != (Proc *) 0; p = p->next) {
- if (p->state == PRUNNING)
- return; /* some processes still running */
- if (p->state > jstate)
- jstate = p->state;
- }
- j->state = jstate;
-
- switch (j->last_proc->state) {
- case PEXITED:
- j->status = WEXITSTATUS(j->last_proc->status);
- break;
- case PSIGNALLED:
- j->status = 128 + WTERMSIG(j->last_proc->status);
- break;
- default:
- j->status = 0;
- break;
- }
-
-#ifdef KSH
- /* Note when co-process dies: can't be done in j_wait() nor
- * remove_job() since neither may be called for non-interactive
- * shells.
- */
- if (j->state == PEXITED || j->state == PSIGNALLED) {
- /* No need to keep co-process input any more
- * (at leasst, this is what ksh93d thinks)
- */
- if (coproc.job == j) {
- coproc.job = (void *) 0;
- /* XXX would be nice to get the closes out of here
- * so they aren't done in the signal handler.
- * Would mean a check in coproc_getfd() to
- * do "if job == 0 && write >= 0, close write".
- */
- coproc_write_close(coproc.write);
- }
- /* Do we need to keep the output? */
- if (j->coproc_id && j->coproc_id == coproc.id
- && --coproc.njobs == 0)
- coproc_readw_close(coproc.read);
- }
-#endif /* KSH */
-
- j->flags |= JF_CHANGED;
-#ifdef JOBS
- if (Flag(FMONITOR) && !(j->flags & JF_XXCOM)) {
- /* Only put stopped jobs at the front to avoid confusing
- * the user (don't want finished jobs effecting %+ or %-)
- */
- if (j->state == PSTOPPED)
- put_job(j, PJ_ON_FRONT);
- if (Flag(FNOTIFY)
- && (j->flags & (JF_WAITING|JF_W_ASYNCNOTIFY)) != JF_WAITING)
- {
- /* Look for the real file descriptor 2 */
- {
- struct env *ep;
- int fd = 2;
-
- for (ep = e; ep; ep = ep->oenv)
- if (ep->savefd && ep->savefd[2])
- fd = ep->savefd[2];
- shf_reopen(fd, SHF_WR, shl_j);
- }
- /* Can't call j_notify() as it removes jobs. The job
- * must stay in the job list as j_waitj() may be
- * running with this job.
- */
- j_print(j, JP_MEDIUM, shl_j);
- shf_flush(shl_j);
- if (!(j->flags & JF_WAITING) && j->state != PSTOPPED)
- remove_job(j, "notify");
- }
- }
-#endif /* JOBS */
- if (!Flag(FMONITOR) && !(j->flags & (JF_WAITING|JF_FG))
- && j->state != PSTOPPED)
- {
- if (j == async_job || (j->flags & JF_KNOWN)) {
- j->flags |= JF_ZOMBIE;
- j->job = -1;
- nzombie++;
- } else
- remove_job(j, "checkjob");
- }
-}
-
-/*
- * Print job status in either short, medium or long format.
- *
- * If jobs are compiled in then this routine expects sigchld to be blocked.
- */
-static void
-j_print(j, how, shf)
- Job *j;
- int how;
- struct shf *shf;
-{
- Proc *p;
- int state;
- WAIT_T status;
- int coredumped;
- char jobchar = ' ';
- char buf[64];
- const char *filler;
- int output = 0;
-
- if (how == JP_PGRP) {
- /* POSIX doesn't say what to do it there is no process
- * group leader (ie, !FMONITOR). We arbitrarily return
- * last pid (which is what $! returns).
- */
- shf_fprintf(shf, "%d\n", j->pgrp ? j->pgrp
- : (j->last_proc ? j->last_proc->pid : 0));
- return;
- }
- j->flags &= ~JF_CHANGED;
- filler = j->job > 10 ? "\n " : "\n ";
- if (j == job_list)
- jobchar = '+';
- else if (j == job_list->next)
- jobchar = '-';
-
- for (p = j->proc_list; p != (Proc *) 0;) {
- coredumped = 0;
- switch (p->state) {
- case PRUNNING:
- strcpy(buf, "Running");
- break;
- case PSTOPPED:
- strcpy(buf, sigtraps[WSTOPSIG(p->status)].mess);
- break;
- case PEXITED:
- if (how == JP_SHORT)
- buf[0] = '\0';
- else if (WEXITSTATUS(p->status) == 0)
- strcpy(buf, "Done");
- else
- shf_snprintf(buf, sizeof(buf), "Done (%d)",
- WEXITSTATUS(p->status));
- break;
- case PSIGNALLED:
- if (WIFCORED(p->status))
- coredumped = 1;
- /* kludge for not reporting `normal termination signals'
- * (ie, SIGINT, SIGPIPE)
- */
- if (how == JP_SHORT && !coredumped
- && (WTERMSIG(p->status) == SIGINT
- || WTERMSIG(p->status) == SIGPIPE)) {
- buf[0] = '\0';
- } else
- strcpy(buf, sigtraps[WTERMSIG(p->status)].mess);
- break;
- }
-
- if (how != JP_SHORT)
- if (p == j->proc_list)
- shf_fprintf(shf, "[%d] %c ", j->job, jobchar);
- else
- shf_fprintf(shf, "%s", filler);
-
- if (how == JP_LONG)
- shf_fprintf(shf, "%5d ", p->pid);
-
- if (how == JP_SHORT) {
- if (buf[0]) {
- output = 1;
- shf_fprintf(shf, "%s%s ",
- buf, coredumped ? " (core dumped)" : null);
- }
- } else {
- output = 1;
- shf_fprintf(shf, "%-20s %s%s%s", buf, p->command,
- p->next ? "|" : null,
- coredumped ? " (core dumped)" : null);
- }
-
- state = p->state;
- status = p->status;
- p = p->next;
- while (p && p->state == state
- && WSTATUS(p->status) == WSTATUS(status))
- {
- if (how == JP_LONG)
- shf_fprintf(shf, "%s%5d %-20s %s%s", filler, p->pid,
- space, p->command, p->next ? "|" : null);
- else if (how == JP_MEDIUM)
- shf_fprintf(shf, " %s%s", p->command,
- p->next ? "|" : null);
- p = p->next;
- }
- }
- if (output)
- shf_fprintf(shf, newline);
-}
-
-/* Convert % sequence to job
- *
- * If jobs are compiled in then this routine expects sigchld to be blocked.
- */
-static Job *
-j_lookup(cp, ecodep)
- const char *cp;
- int *ecodep;
-{
- Job *j, *last_match;
- Proc *p;
- int len, job = 0;
-
- if (digit(*cp)) {
- job = atoi(cp);
- /* Look for last_proc->pid (what $! returns) first... */
- for (j = job_list; j != (Job *) 0; j = j->next)
- if (j->last_proc && j->last_proc->pid == job)
- return j;
- /* ...then look for process group (this is non-POSIX),
- * but should not break anything (so FPOSIX isn't used).
- */
- for (j = job_list; j != (Job *) 0; j = j->next)
- if (j->pgrp && j->pgrp == job)
- return j;
- if (ecodep)
- *ecodep = JL_NOSUCH;
- return (Job *) 0;
- }
- if (*cp != '%') {
- if (ecodep)
- *ecodep = JL_INVALID;
- return (Job *) 0;
- }
- switch (*++cp) {
- case '\0': /* non-standard */
- case '+':
- case '%':
- if (job_list != (Job *) 0)
- return job_list;
- break;
-
- case '-':
- if (job_list != (Job *) 0 && job_list->next)
- return job_list->next;
- break;
-
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- job = atoi(cp);
- for (j = job_list; j != (Job *) 0; j = j->next)
- if (j->job == job)
- return j;
- break;
-
- case '?': /* %?string */
- last_match = (Job *) 0;
- for (j = job_list; j != (Job *) 0; j = j->next)
- for (p = j->proc_list; p != (Proc *) 0; p = p->next)
- if (strstr(p->command, cp+1) != (char *) 0) {
- if (last_match) {
- if (ecodep)
- *ecodep = JL_AMBIG;
- return (Job *) 0;
- }
- last_match = j;
- }
- if (last_match)
- return last_match;
- break;
-
- default: /* %string */
- len = strlen(cp);
- last_match = (Job *) 0;
- for (j = job_list; j != (Job *) 0; j = j->next)
- if (strncmp(cp, j->proc_list->command, len) == 0) {
- if (last_match) {
- if (ecodep)
- *ecodep = JL_AMBIG;
- return (Job *) 0;
- }
- last_match = j;
- }
- if (last_match)
- return last_match;
- break;
- }
- if (ecodep)
- *ecodep = JL_NOSUCH;
- return (Job *) 0;
-}
-
-static Job *free_jobs;
-static Proc *free_procs;
-
-/* allocate a new job and fill in the job number.
- *
- * If jobs are compiled in then this routine expects sigchld to be blocked.
- */
-static Job *
-new_job()
-{
- int i;
- Job *newj, *j;
-
- if (free_jobs != (Job *) 0) {
- newj = free_jobs;
- free_jobs = free_jobs->next;
- } else
- newj = (Job *) alloc(sizeof(Job), APERM);
-
- /* brute force method */
- for (i = 1; ; i++) {
- for (j = job_list; j && j->job != i; j = j->next)
- ;
- if (j == (Job *) 0)
- break;
- }
- newj->job = i;
-
- return newj;
-}
-
-/* Allocate new process strut
- *
- * If jobs are compiled in then this routine expects sigchld to be blocked.
- */
-static Proc *
-new_proc()
-{
- Proc *p;
-
- if (free_procs != (Proc *) 0) {
- p = free_procs;
- free_procs = free_procs->next;
- } else
- p = (Proc *) alloc(sizeof(Proc), APERM);
-
- return p;
-}
-
-/* Take job out of job_list and put old structures into free list.
- * Keeps nzombies, last_job and async_job up to date.
- *
- * If jobs are compiled in then this routine expects sigchld to be blocked.
- */
-static void
-remove_job(j, where)
- Job *j;
- const char *where;
-{
- Proc *p, *tmp;
- Job **prev, *curr;
-
- prev = &job_list;
- curr = *prev;
- for (; curr != (Job *) 0 && curr != j; prev = &curr->next, curr = *prev)
- ;
- if (curr != j) {
- internal_errorf(0, "remove_job: job not found (%s)", where);
- return;
- }
- *prev = curr->next;
-
- /* free up proc structures */
- for (p = j->proc_list; p != (Proc *) 0; ) {
- tmp = p;
- p = p->next;
- tmp->next = free_procs;
- free_procs = tmp;
- }
-
- if ((j->flags & JF_ZOMBIE) && j->ppid == procpid)
- --nzombie;
- j->next = free_jobs;
- free_jobs = j;
-
- if (j == last_job)
- last_job = (Job *) 0;
- if (j == async_job)
- async_job = (Job *) 0;
-}
-
-/* put j in a particular location (taking it out job_list if it is there
- * already)
- *
- * If jobs are compiled in then this routine expects sigchld to be blocked.
- */
-static void
-put_job(j, where)
- Job *j;
- int where;
-{
- Job **prev, *curr;
-
- /* Remove job from list (if there) */
- prev = &job_list;
- curr = job_list;
- for (; curr && curr != j; prev = &curr->next, curr = *prev)
- ;
- if (curr == j)
- *prev = curr->next;
-
- switch (where) {
- case PJ_ON_FRONT:
- j->next = job_list;
- job_list = j;
- break;
-
- case PJ_PAST_STOPPED:
- prev = &job_list;
- curr = job_list;
- for (; curr && curr->state == PSTOPPED; prev = &curr->next,
- curr = *prev)
- ;
- j->next = curr;
- *prev = j;
- break;
- }
-}
-
-/* nuke a job (called when unable to start full job).
- *
- * If jobs are compiled in then this routine expects sigchld to be blocked.
- */
-static void
-kill_job(j)
- Job *j;
-{
- Proc *p;
-
- for (p = j->proc_list; p != (Proc *) 0; p = p->next)
- if (p->pid != 0)
- (void) kill(p->pid, SIGKILL);
-}
-
-/* put a more useful name on a process than snptreef does (in certain cases) */
-static void
-fill_command(c, len, t)
- char *c;
- int len;
- struct op *t;
-{
- int alen;
- char **ap;
-
- if (t->type == TEXEC || t->type == TCOM) {
- if (t->type == TCOM)
- ap = eval(t->args, DOBLANK|DONTRUNCOMMAND);
- else
- ap = t->args;
- --len; /* save room for the null */
- while (len > 0 && *ap != (char *) 0) {
- alen = strlen(*ap);
- if (alen > len)
- alen = len;
- memcpy(c, *ap, alen);
- c += alen;
- len -= alen;
- if (len > 0) {
- *c++ = ' '; len--;
- }
- ap++;
- }
- *c = '\0';
- } else
- snptreef(c, len, "%T", t);
-}
diff --git a/bin/pdksh/ksh.1tbl b/bin/pdksh/ksh.1tbl
deleted file mode 100644
index 651f25fd765..00000000000
--- a/bin/pdksh/ksh.1tbl
+++ /dev/null
@@ -1,3298 +0,0 @@
-'\" t
-.\" $OpenBSD: ksh.1tbl,v 1.3 1996/11/21 08:18:19 downsj Exp $
-.\"{{{}}}
-.\"{{{ Notes about man page
-.\" - use the pseudo-macros .sh( and .sh) to begin and end sh-specific
-.\" text and .ksh( and .ksh) for ksh specific text.
-.\" - put i.e., e.g. and etc. in italics
-.\"}}}
-.\"{{{ To do
-.\" todo: Things not covered that should be:
-.\" - distinguish (POSIX) special built-in's, (POSIX) regular built-in's,
-.\" and sh/ksh weirdo built-in's (put S,R,X superscripts after command
-.\" name in built-in commands section?)
-.\" - need to be consistent about notation for `See section-name', `
-.\" See description of foobar command', `See section section-name', etc.
-.\" - need to use the term `external command' meaning `a command that is
-.\" executed using execve(2)' (as opposed to a built-in command or
-.\" function) for more clear description.
-.\"}}}
-.\"{{{ Title
-.TH KSH 1 "August 19, 1996" "" "User commands"
-.\"}}}
-.\"{{{ Name
-.SH NAME
-ksh \- Public domain Korn shell
-.\"}}}
-.\"{{{ Synopsis
-.SH SYNOPSIS
-.ad l
-\fBksh\fP
-[\fB\(+-abCefhikmnprsuvxX\fP] [\fB\(+-o\fP \fIoption\fP] [ [ \fB\-c\fP \fIcommand-string\fP [\fIcommand-name\fP] | \fB\-s\fP | \fIfile\fP ] [\fIargument\fP ...] ]
-.ad b
-.\"}}}
-.\"{{{ Description
-.SH DESCRIPTION
-\fBksh\fP is a command interpreter that is intended for both
-interactive and shell script use. Its command language is a superset
-of the \fIsh\fP(1) shell language.
-.\"{{{ Shell Startup
-.SS "Shell Startup"
-The following options can be specified only on the command line:
-.IP "\fB\-c\fP \fIcommand-string\fP"
-the shell executes the command(s) contained in \fIcommand-string\fP
-.IP \fB\-i\fP
-interactive mode \(em see below
-.IP \fB\-l\fP
-login shell \(em see below
-interactive mode \(em see below
-.IP \fB\-s\fP
-the shell reads commands from standard input; all non-option arguments
-are positional parameters
-.IP \fB\-r\fP
-restricted mode \(em see below
-.PP
-In addition to the above, the options described in the \fBset\fP built-in
-command can also be used on the command line.
-.PP
-If neither the \fB\-c\fP nor the \fB\-s\fP options are specified, the
-first non-option argument specifies the name of a file the shell reads
-commands from; if there are no non-option arguments, the shell reads
-commands from standard input.
-The name of the shell (\fIi.e.\fP, the contents of the \fB$0\fP) parameter
-is determined as follows: if the \fB\-c\fP option is used and there is
-a non-option argument, it is used as the name; if commands are being
-read from a file, the file is used as the name; otherwise the name
-the shell was called with (\fIi.e.\fP, argv[0]) is used.
-.PP
-A shell is \fBinteractive\fP if the \fB\-i\fP option is used or
-if both standard input and standard error are attached to a tty.
-An interactive shell has job control enabled (if available),
-ignores the INT, QUIT and TERM signals, and prints prompts before
-reading input (see \fBPS1\fP and \fBPS2\fP parameters).
-For non-interactive shells, the \fBtrackall\fP option is on by default
-(see \fBset\fP command below).
-.PP
-A shell is \fBrestricted\fP if the \fB\-r\fP option is used or if either
-the basename of the name the shell is invoked with or the \fBSHELL\fP
-parameter match the pattern *r*sh (\fIe.g.\fP, rsh, rksh, rpdksh, \fIetc.\fP).
-The following restrictions come into effect after the shell processes
-any profile and \fB$ENV\fP files:
-.nr P2 \n(PD
-.nr PD 0
-.IP \ \ \(bu
-the \fBcd\fP command is disabled
-.IP \ \ \(bu
-the \fBSHELL\fP, \fBENV\fP and \fBPATH\fP parameters can't be changed
-.IP \ \ \(bu
-command names can't be specified with absolute or relative paths
-.IP \ \ \(bu
-the \fB\-p\fP option of the \fBcommand\fP built-in can't be used
-.IP \ \ \(bu
-redirections that create files can't be used (\fIi.e.\fP, \fB>\fP,
-\fB>|\fP, \fB>>\fP, \fB<>\fP)
-.nr PD \n(P2
-.PP
-A shell is \fBprivileged\fP if the \fB\-p\fP option is used or if
-the real user-id or group-id does not match the effective user-id
-or group-id (see \fIgetuid\fP(2), \fIgetgid\fP(2)).
-A privileged shell does not process $HOME/.profile nor the \fBENV\fP
-parameter (see below), instead the file /etc/suid_profile is processed.
-Clearing the privileged option causes the shell to set its effective
-user-id (group-id) to its real user-id (group-id).
-.PP
-If the basename of the name the shell is called with (\fIi.e.\fP, argv[0])
-starts with \fB\-\fP or if the \fB\-l\fP option is used, the shell is assumed
-to be a login shell and the shell reads and executes the contents of
-\fB/etc/profile\fP and \fB$HOME/.profile\fP if they exist and are readable.
-.PP
-If the \fBENV\fP parameter is set when the shell starts (or, in the
-case of login shells, after any profiles are processed), its value
-is subjected to parameter, command, arithmetic and tilde substitution and
-the resulting file (if any) is read and executed.
-If \fBENV\fP parameter is not set (and not null) and pdksh was compiled
-with the \fBDEFAULT_ENV\fP macro defined, the file named in that macro
-is included (after the above mentioned substitutions have been performed).
-.PP
-The exit status of the shell is 127 if the command file specified
-on the command line could not be opened, or non-zero if a fatal syntax
-error occurred during the execution of a script.
-In the absence of fatal errors, the exit status is that of the last
-command executed, or zero, if no command is executed.
-.\"}}}
-.\"{{{ Command Syntax
-.SS "Command Syntax"
-.\"{{{ words and tokens
-The shell begins parsing its input by breaking it into \fIword\fPs.
-Words, which are sequences of characters, are delimited by unquoted
-\fIwhite-space\fP characters (space, tab and newline) or \fImeta-characters\fP
-(\fB<\fP, \fB>\fP, \fB|\fP, \fB;\fP, \fB&\fP, \fB(\fP and \fB)\fP).
-Aside from delimiting words, spaces and tabs are ignored, while
-newlines usually delimit commands.
-The meta-characters are used in building the following tokens:
-\fB<\fP, \fB<&\fP, \fB<<\fP, \fB>\fP, \fB>&\fP, \fB>>\fP, \fIetc.\fP are
-used to specify redirections (see Input/Output Redirection below);
-\fB|\fP is used to create pipelines;
-\fB|&\fP is used to create co-processes (see Co-Processes below);
-\fB;\fP is used to separate commands;
-\fB&\fP is used to create asynchronous pipelines;
-\fB&&\fP and \fB||\fP are used to specify conditional execution;
-\fB;;\fP is used in \fBcase\fP statements;
-\fB((\fP .. \fB))\fP are used in arithmetic expressions;
-and lastly,
-\fB(\fP .. \fB)\fP are used to create subshells.
-.PP
-White-space and meta-characters can be quoted individually using
-backslash (\fB\e\fP), or in groups using double (\fB"\fP) or single (\fB'\fP)
-quotes.
-Note that the following characters are also treated specially by the shell and
-must be quoted if they are to represent themselves:
-\fB\e\fP, \fB"\fP, \fB'\fP, \fB#\fP, \fB$\fP, \fB`\fP, \fB~\fP, \fB{\fP,
-\fB}\fP, \fB*\fP, \fB?\fP and \fB[\fP.
-The first three of these are the above mentioned quoting characters
-(see Quoting below);
-\fB#\fP, if used at the beginning of a word, introduces a comment \(em everything
-after the \fB#\fP up to the nearest newline is ignored;
-\fB$\fP is used to introduce parameter, command and arithmetic substitutions
-(see Substitution below);
-\fB`\fP introduces an old-style command substitution
-(see Substitution below);
-\fB~\fP begins a directory expansion (see Tilde Expansion below);
-\fB{\fP and \fB}\fP delimit \fIcsh\fP(1) style alternations
-(see Brace Expansion below);
-and, finally, \fB*\fP, \fB?\fP and \fB[\fP are used in file name generation
-(see File Name Patterns below).
-.\"}}}
-.\"{{{ simple-command
-.PP
-As words and tokens are parsed, the shell builds commands, of which
-there are two basic types: \fIsimple-commands\fP, typically programs
-that are executed, and \fIcompound-commands\fP, such as \fBfor\fP and
-\fBif\fP statements, grouping constructs and function definitions.
-.PP
-A simple-command consists of some combination of parameter assignments (see
-Parameters below), input/output redirections (see Input/Output Redirections
-below), and command words; the only restriction is that parameter assignments
-come before any command words.
-The command words, if any, define the command that is to be executed and its
-arguments.
-The command may be a shell built-in command, a function or an \fIexternal
-command\fP, \fIi.e.\fP, a separate executable file that is located using the
-\fBPATH\fP parameter (see Command Execution below).
-Note that all command constructs have an \fIexit status\fP: for external
-commands, this is related to the status returned by \fIwait\fP(2) (if the
-command could not be found, the exit status is 127, if it could not be
-executed, the exit status is 126);
-the exit status of other command constructs (built-in commands, functions,
-compound-commands, pipelines, lists, \fIetc.\fP) are all well defined and are
-described where the construct is described.
-The exit status of a command consisting only of parameter assignments is that
-of the last command substitution performed during the parameter assignment
-or zero if there were no command substitutions.
-.\"}}}
-.\"{{{ pipeline
-.PP
-Commands can be chained together using the \fB|\fP token to
-form \fIpipelines\fP, in which the standard output of each command but
-the last is piped (see \fIpipe\fP(2)) to the standard input of the following
-command.
-The exit status of a pipeline is that of its last command.
-A pipeline may be prefixed by the \fB!\fP reserved word which
-causes the exit status of the pipeline to be logically
-complemented: if the original status was 0 the complemented status will
-be 1, and if the original status was not 0, then the complemented
-status will be 0.
-.\"}}}
-.\"{{{ lists
-.PP
-\fILists\fP of commands can be created by separating pipelines by
-any of the following tokens: \fB&&\fP, \fB||\fP, \fB&\fP, \fB|&\fP and \fB;\fP.
-The first two are for conditional execution: \fIcmd1\fP \fB&&\fP \fIcmd2\fP
-executes \fIcmd2\fP only if the exit status of \fIcmd1\fP is zero;
-\fB||\fP is the opposite \(em \fIcmd2\fP is executed only if the exit status
-of \fIcmd1\fP is non-zero.
-\fB&&\fP and \fB||\fP have equal precedence which is higher than that of
-\fB&\fP, \fB|&\fP and \fB;\fP, which also have equal precedence.
-The \fB&\fP token causes the preceding command to be executed asynchronously,
-that is, the shell starts the command, but does not wait for it to complete
-(the shell does keep track of the status of asynchronous commands \(em see
-Job Control below).
-When an asynchronous command is started when job control is disabled
-(\fIi.e.\fP, in most scripts), the command is started with signals INT
-and QUIT ignored and with input redirected from /dev/null
-(however, redirections specified in the asynchronous command have precedence).
-The \fB|&\fP operator starts a \fIco-process\fP which is special kind of
-asynchronous process (see Co-Processes below).
-Note that a command must follow the \fB&&\fP and \fB||\fP operators, while
-a command need not follow \fB&\fP, \fB|&\fP and \fB;\fP.
-The exit status of a list is that of the last command executed, with the
-exception of asynchronous lists, for which the exit status is 0.
-.\"}}}
-.\"{{{ compound-commands
-.PP
-Compound commands are created using the following reserved words \(em these
-words are only recognized if they are unquoted and if they are used as
-the first word of a command (\fIi.e.\fP, they can't be preceded by parameter
-assignments or redirections):
-.TS
-center;
-lfB lfB lfB lfB lfB .
-case else function then !
-do esac if time [[
-done fi in until {
-elif for select while }
-.TE
-\fBNote:\fP Some shells (but not this one) execute control structure commands
-in a subshell when one or more of their file descriptors are redirected, so
-any environment changes inside them may fail.
-To be portable, the \fBexec\fP statement should be used instead to redirect
-file descriptors before the control structure.
-.PP
-In the following compound command descriptions, command lists (denoted as
-\fIlist\fP) that are followed by reserved words must end with a
-semi-colon, a newline or a (syntactically correct) reserved word.
-For example,
-.RS
-\fB{ echo foo; echo bar; }\fP
-.br
-\fB{ echo foo; echo bar<newline>}\fP
-.br
-\fB{ { echo foo; echo bar; } }\fP
-.RE
-are all valid, but
-.RS
-\fB{ echo foo; echo bar }\fP
-.RE
-is not.
-.\"{{{ ( list )
-.IP "\fB(\fP \fIlist\fP \fB)\fP"
-Execute \fIlist\fP in a subshell. There is no implicit way to pass
-environment changes from a subshell back to its parent.
-.\"}}}
-.\"{{{ { list }
-.IP "\fB{\fP \fIlist\fP \fB}\fP"
-Compound construct; \fIlist\fP is executed, but not in a subshell.
-Note that \fB{\fP and \fB}\fP are reserved words, not meta-characters.
-.\"}}}
-.\"{{{ case word in [ [ ( ] pattern [ | pattern ] ... ) list ;; ] ... esac
-.IP "\fBcase\fP \fIword\fP \fBin\fP [ [\fB(\fP] \fIpattern\fP [\fB|\fP \fIpattern\fP] ... \fB)\fP \fIlist\fP \fB;;\fP ] ... \fBesac\fP"
-The \fBcase\fP statement attempts to match \fIword\fP against the specified
-\fIpattern\fPs; the \fIlist\fP associated with the first successfully matched
-pattern is executed. Patterns used in \fBcase\fP statements are the same as
-those used for file name patterns except that the restrictions regarding
-\fB\&.\fP and \fB/\fP are dropped. Note that any unquoted space before and
-after a pattern is stripped; any space with a pattern must be quoted. Both the
-word and the patterns are subject to parameter, command, and arithmetic
-substitution as well as tilde substitution.
-For historical reasons, open and close braces may be used instead
-of \fBin\fP and \fBesac\fP (\fIe.g.\fP, \fBcase $foo { *) echo bar; }\fP).
-The exit status of a \fBcase\fP statement is that of the executed \fIlist\fP;
-if no \fIlist\fP is executed, the exit status is zero.
-.\"}}}
-.\"{{{ for name [ in word ... term ] do list done
-.IP "\fBfor\fP \fIname\fP [ \fBin\fP \fIword\fP ... \fIterm\fP ] \fBdo\fP \fIlist\fP \fBdone\fP"
-where \fIterm\fP is either a newline or a \fB;\fP.
-For each \fIword\fP in the specified word list, the parameter \fIname\fP is
-set to the word and \fIlist\fP is executed. If \fBin\fP is not used to
-specify a word list, the positional parameters (\fB"$1"\fP, \fB"$2"\fP,
-\fIetc.\fP) are used instead.
-For historical reasons, open and close braces may be used instead
-of \fBdo\fP and \fBdone\fP (\fIe.g.\fP, \fBfor i; { echo $i; }\fP).
-The exit status of a \fBfor\fP statement is the last exit status
-of \fIlist\fP; if \fIlist\fP is never executed, the exit status is zero.
-.\"}}}
-.\"{{{ if list then list [ elif list then list ] ... [ else list ] fi
-.IP "\fBif\fP \fIlist\fP \fBthen\fP \fIlist\fP [\fBelif\fP \fIlist\fP \fBthen\fP \fIlist\fP] ... [\fBelse\fP \fIlist\fP] \fBfi\fP"
-If the exit status of the first \fIlist\fP is zero, the second \fIlist\fP
-is executed; otherwise the \fIlist\fP following the \fBelif\fP, if any, is
-executed with similar consequences. If all the lists following the \fBif\fP
-and \fBelif\fPs fail (\fIi.e.\fP, exit with non-zero status), the \fIlist\fP
-following the \fBelse\fP is executed.
-The exit status of an \fBif\fP statement is that
-of non-conditional \fIlist\fP that is executed; if no non-conditional
-\fIlist\fP is executed, the exit status is zero.
-.\"}}}
-.\"{{{ select name [ in word ... ] do list done
-.IP "\fBselect\fP \fIname\fP [ \fBin\fP \fIword\fP ... \fIterm\fP ] \fBdo\fP \fIlist\fP \fBdone\fP"
-where \fIterm\fP is either a newline or a \fB;\fP.
-The \fBselect\fP statement provides an automatic method of presenting
-the user with a menu and selecting from it.
-An enumerated list of the specified \fIwords\fP is printed on standard
-error, followed by a prompt (\fBPS3\fP, normally `\fB#? \fP').
-A number corresponding to one of the enumerated words is then read
-from standard input, \fIname\fP is set to the selected word (or is
-unset if the selection is not valid), \fBREPLY\fP
-is set to what was read (leading/trailing space is stripped),
-and \fIlist\fP is executed.
-If a blank line (\fIi.e.\fP, zero or more \fBIFS\fP characters) is entered,
-the menu is re-printed without executing \fIlist\fP.
-When \fIlist\fP completes, the enumerated list is printed if \fBREPLY\fP
-is null, the prompt is printed and so on.
-This process is continues until an end-of-file is read, an interrupt is
-received or a break statement is executed inside the loop.
-If \fBin\fP \fIword\fP \fB\&...\fP is omitted, the positional parameters
-are used (\fIi.e.\fP, \fB"$1"\fP, \fB"$2"\fP, \fIetc.\fP).
-For historical reasons, open and close braces may be used instead
-of \fBdo\fP and \fBdone\fP (\fIe.g.\fP, \fBselect i; { echo $i; }\fP).
-The exit status of a \fBselect\fP statement is zero if a break statement
-is used to exit the loop, non-zero otherwise.
-.\"}}}
-.\"{{{ until list do list done
-.IP "\fBuntil\fP \fIlist\fP \fBdo\fP \fIlist\fP \fBdone\fP"
-This works like \fBwhile\fP, except that the body is executed only while the
-exit status of the first \fIlist\fP is non-zero.
-.\"}}}
-.\"{{{ while list do list done
-.IP "\fBwhile\fP \fIlist\fP \fBdo\fP \fIlist\fP \fBdone\fP"
-A \fBwhile\fP is a prechecked loop. Its body is executed as often
-as the exit status of the first \fIlist\fP is zero.
-The exit status of a \fBwhile\fP statement is the last exit status
-of the \fIlist\fP in the body of the loop; if the body is not executed,
-the exit status is zero.
-.\"}}}
-.\"{{{ function name { list }
-.IP "\fBfunction\fP \fIname\fP \fB{\fP \fIlist\fP \fB}\fP"
-Defines the function \fIname\fP.
-See Functions below.
-Note that redirections specified after a function definition are
-performed whenever the function is executed, not when the function
-definition is executed.
-.\"}}}
-.\"{{{ name () command
-.IP "\fIname\fP \fB()\fP \fIcommand\fP"
-Mostly the same as \fBfunction\fP.
-See Functions below.
-.\"}}}
-.\"{{{ (( expression ))
-.IP "\fB((\fP \fIexpression\fP \fB))\fP"
-The arithmetic expression \fIexpression\fP is evaluated;
-equivalent to \fBlet "\fP\fIexpression\fP\fB"\fP.
-See Arithmetic Expressions and the \fBlet\fP command below.
-.\"}}}
-.\"{{{ [[ expression ]]
-.IP "\fB[[\fP \fIexpression\fP \fB]]\fP"
-Similar to the \fBtest\fP and \fB[\fP \&... \fB]\fP commands (described later),
-with the following exceptions:
-.RS
-.nr P2 \n(PD
-.nr PD 0
-.IP \ \ \(bu
-Field splitting and file name generation are not performed on
-arguments.
-.IP \ \ \(bu
-The \fB\-a\fP (and) and \fB\-o\fP (or) operators are replaced with
-\fB&&\fP and \fB||\fP, respectively.
-.IP \ \ \(bu
-Operators (\fIe.g.\fP, \fB\-f\fP, \fB=\fP, \fB!\fP, \fIetc.\fP) must be unquoted.
-.IP \ \ \(bu
-The second operand of \fB!=\fP and \fB=\fP
-expressions are patterns (\fIe.g.\fP, the comparison in
-.ce
-\fB[[ foobar = f*r ]]\fP
-succeeds).
-.IP \ \ \(bu
-There are two additional binary operators: \fB<\fP and \fB>\fP
-which return true if their first string operand is less than,
-or greater than, their second string operand, respectively.
-.IP \ \ \(bu
-The single argument form
-of \fBtest\fP, which tests if the argument has non-zero length, is not valid
-- explicit operators must be always be used, \fIe.g.\fP, instead of
-.ce
-\fB[\fP \fIstr\fP \fB]\fP
-use
-.ce
-\fB[[ \-n \fP\fIstr\fP\fB ]]\fP
-.IP \ \ \(bu
-Parameter, command and arithmetic substitutions are performed as
-expressions are evaluated and lazy expression evaluation is used for
-the \fB&&\fP and \fB||\fP operators.
-This means that in the statement
-.ce
-\fB[[ -r foo && $(< foo) = b*r ]]\fP
-the \fB$(< foo)\fP is evaluated if and only if the file \fBfoo\fP exists
-and is readable.
-.nr PD \n(P2
-.RE
-.\"}}}
-.\"}}}
-.\"}}}
-.\"{{{ Quoting
-.SS Quoting
-Quoting is used to prevent the shell from treating characters or words
-specially.
-There are three methods of quoting: First, \fB\e\fP quotes
-the following character, unless it is at the end of a line, in which
-case both the \fB\e\fP and the newline are stripped.
-Second, a single quote (\fB'\fP) quotes everything up to the next single
-quote (this may span lines).
-Third, a double quote (\fB"\fP) quotes all characters,
-except \fB$\fP, \fB`\fP and \fB\e\fP, up to the next unquoted double quote.
-\fB$\fP and \fB`\fP inside double quotes have their usual meaning (\fIi.e.\fP,
-parameter, command or arithmetic substitution) except no field splitting
-is carried out on the results of double-quoted substitutions.
-If a \fB\e\fP inside a double-quoted string is followed by \fB\e\fP, \fB$\fP,
-\fB`\fP or \fB"\fP, it is replaced by the second character; if it is
-followed by a newline, both the \fB\e\fP and the newline are stripped;
-otherwise, both the \fB\e\fP and the character following are unchanged.
-.PP
-Note: see POSIX Mode below for a special rule regarding sequences
-of the form \fB"\fP...\fB`\fP...\fB\e"\fP...\fB`\fP..\fB"\fP.
-.\"}}}
-.\"{{{ Aliases
-.SS "Aliases"
-There are two types of aliases: normal command aliases and tracked
-aliases. Command aliases are normally used as a short hand for a long
-or often used command. The shell expands command aliases (\fIi.e.\fP,
-substitutes the alias name for its value) when it reads the first word
-of a command. An expanded alias is re-processed to check for more
-aliases. If a command alias ends in a space or tab, the following word
-is also checked for alias expansion. The alias expansion process stops
-when a word that is not an alias is found, when a quoted word is found
-or when an alias word that is currently being expanded is found.
-.PP
-The following command aliases are defined automatically by the shell:
-.ft B
-.RS
-autoload='typeset \-fu'
-.br
-functions='typeset \-f'
-.br
-hash='alias \-t'
-.br
-history='fc \-l'
-.br
-integer='typeset \-i'
-.br
-local='typeset'
-.br
-login='exec login'
-.br
-newgrp='exec newgrp'
-.br
-nohup='nohup '
-.br
-r='fc \-e \-'
-.br
-stop='kill \-STOP'
-.br
-suspend='kill \-STOP $$'
-.br
-type='whence \-v'
-.RE
-.ft P
-.PP
-Tracked aliases allow the shell to remember where it found a particular
-command. The first time the shell does a path search for a command that
-is marked as a tracked alias, it saves the full path of the command.
-The next time the command is executed, the shell checks the saved path
-to see that it is still valid, and if so, avoids repeating the path
-search. Tracked aliases can be listed and created using \fBalias
-\-t\fP. Note that changing the \fBPATH\fP parameter clears the saved
-paths for all tracked aliases. If the \fBtrackall\fP option is set (\fIi.e.\fP,
-\fBset \-o trackall\fP or \fBset \-h\fP), the shell tracks all
-commands. This option is set automatically for non-interactive shells.
-For interactive shells, only the following commands are automatically
-tracked: \fBcat\fP, \fBcc\fP, \fBchmod\fP, \fBcp\fP, \fBdate\fP, \fBed\fP,
-\fBemacs\fP, \fBgrep\fP, \fBls\fP, \fBmail\fP, \fBmake\fP, \fBmv\fP,
-\fBpr\fP, \fBrm\fP, \fBsed\fP, \fBsh\fP, \fBvi\fP and \fBwho\fP.
-.\"}}}
-.\"{{{ Substitution
-.SS "Substitution"
-The first step the shell takes in executing a simple-command is to
-perform substitutions on the words of the command.
-There are three kinds of substitution: parameter, command and arithmetic.
-Parameter substitutions, which are described in detail in the next section,
-take the form \fB$name\fP or \fB${\fP...\fB}\fP; command substitutions take
-the form \fB$(\fP\fIcommand\fP\fB)\fP or \fB`\fP\fIcommand\fP\fB`\fP;
-and arithmetic substitutions take the form \fB$((\fP\fIexpression\fP\fB))\fP.
-.PP
-If a substitution appears outside of double quotes, the results of the
-substitution are generally subject to word or field splitting according to
-the current value of the \fBIFS\fP parameter.
-The \fBIFS\fP parameter specifies a list of characters which
-are used to break a string up into several words;
-any characters from the set space, tab and newline that appear in the
-IFS characters are called \fIIFS white space\fP.
-Sequences of one or more IFS white space characters, in combination with
-zero or one non-IFS white space characters delimit a field.
-As a special case, leading and trailing IFS white space is stripped (\fIi.e.\fP,
-no leading or trailing empty field is created by it); leading or trailing
-non-IFS white space does create an empty field.
-Example: if \fBIFS\fP is set to `<space>:', the sequence of characters
-`<space>A<space>:<space><space>B::D' contains four fields: `A', `B', `' and `D'.
-Note that if the \fBIFS\fP parameter is set to the null string, no
-field splitting is done; if the parameter is unset, the default value
-of space, tab and newline is used.
-.PP
-The results of substitution are, unless otherwise specified, also subject
-to brace expansion and file name expansion (see the relevant sections
-below).
-.PP
-A command substitution is replaced by the output generated by the specified
-command, which is run in a subshell.
-For \fB$(\fP\fIcommand\fP\fB)\fP substitutions, normal quoting rules
-are used when \fIcommand\fP is parsed, however, for the
-\fB`\fP\fIcommand\fP\fB`\fP form, a \fB\e\fP followed by any of
-\fB$\fP, \fB`\fP or \fB\e\fP is stripped (a \fB\e\fP followed by any other
-character is unchanged).
-As a special case in command substitutions, a command of the form
-\fB<\fP \fIfile\fP is interpreted to mean substitute the contents
-of \fIfile\fP ($(< foo) has the same effect as $(cat foo), but it
-is carried out more efficiently because no process is started).
-.br
-.\"todo: fix this( $(..) parenthesis counting).
-NOTE: \fB$(\fP\fIcommand\fP\fB)\fP expressions are currently parsed by
-finding the matching parenthesis, regardless of quoting. This will hopefully
-be fixed soon.
-.PP
-Arithmetic substitutions are replaced by the value of the specified
-expression.
-For example, the command \fBecho $((2+3*4))\fP prints 14.
-See Arithmetic Expressions for a description of an \fIexpression\fP.
-.\"}}}
-.\"{{{ Parameters
-.SS "Parameters"
-Parameters are shell variables; they can be assigned values and
-their values can be accessed using a parameter substitution.
-A parameter name is either one of the special single punctuation or digit
-character parameters described below, or a letter followed by zero or more
-letters or digits (`_' counts as a letter).
-Parameter substitutions take the form \fB$\fP\fIname\fP or
-\fB${\fP\fIname\fP\fB}\fP, where \fIname\fP is a parameter name.
-If substitution is performed on a parameter that is not set, a null
-string is substituted unless the \fBnounset\fP option (\fBset \-o nounset\fP
-or \fBset \-u\fP) is set, in which case an error occurs.
-.PP
-.\"{{{ parameter assignment
-Parameters can be assigned values in a number of ways.
-First, the shell implicitly sets some parameters like \fB#\fP, \fBPWD\fP,
-etc.; this is the only way the special single character parameters are
-set.
-Second, parameters are imported from the shell's environment at startup.
-Third, parameters can be assigned values on the command line, for example,
-`\fBFOO=bar\fP' sets the parameter FOO to bar; multiple parameter
-assignments can be given on a single command line and they can
-be followed by a simple-command, in which case the assignments are
-in effect only for the duration of the command (such assignments are
-also exported, see below for implications of this).
-Note that both the parameter name and the \fB=\fP must be unquoted for
-the shell to recognize a parameter assignment.
-The fourth way of setting a parameter is with the \fBexport\fP, \fBreadonly\fP
-and \fBtypeset\fP commands; see their descriptions in the Command Execution
-section.
-Fifth, \fBfor\fP and \fBselect\fP loops set parameters as well as
-the \fBgetopts\fP, \fBread\fP and \fBset \-A\fP commands.
-Lastly, parameters can be assigned values using assignment operators
-inside arithmetic expressions (see Arithmetic Expressions below) or
-using the \fB${\fP\fIname\fP\fB=\fP\fIvalue\fP\fB}\fP form
-of parameter substitution (see below).
-.\"}}}
-.PP
-.\"{{{ environment
-Parameters with the export attribute (set using the \fBexport\fP or
-\fBtypeset \-x\fP commands, or by parameter assignments followed by simple
-commands) are put in the environment (see \fIenviron\fP(5)) of commands
-run by the shell as \fIname\fP\fB=\fP\fIvalue\fP pairs.
-The order in which parameters appear in the environment of a command
-is unspecified.
-When the shell starts up, it extracts parameters and their values from its
-environment and automatically sets the export attribute for those parameters.
-.\"}}}
-.\"{{{ ${name[:][-+=?]word}
-.PP
-Modifiers can be applied to the \fB${\fP\fIname\fP\fB}\fP form of parameter
-substitution:
-.IP \fB${\fP\fIname\fP\fB:-\fP\fIword\fP\fB}\fP
-if \fIname\fP is set and not null, it is substituted, otherwise \fIword\fP is
-substituted.
-.IP \fB${\fP\fIname\fP\fB:+\fP\fIword\fP\fB}\fP
-if \fIname\fP is set and not null, \fIword\fP is substituted, otherwise nothing is substituted.
-.IP \fB${\fP\fIname\fP\fB:=\fP\fIword\fP\fB}\fP
-if \fIname\fP is set and not null, it is substituted, otherwise it is
-assigned \fIword\fP and the resulting value of \fIname\fP is substituted.
-.IP \fB${\fP\fIname\fP\fB:?\fP\fIword\fP\fB}\fP
-if \fIname\fP is set and not null, it is substituted, otherwise \fIword\fP
-is printed on standard error (preceded by \fIname\fP:) and an error occurs
-(normally causing termination of a shell script, function or \&.-script).
-If word is omitted the string `parameter null or not set' is used instead.
-.PP
-In the above modifiers, the \fB:\fP can be omitted, in which case the
-conditions only depend on \fIname\fP being set (as opposed to set and
-not null).
-If \fIword\fP is needed, parameter, command, arithmetic and tilde substitution
-are performed on it; if \fIword\fP is not needed, it is not evaluated.
-.\"}}}
-.PP
-The following forms of parameter substitution can also be used:
-.\"{{{ ${#name}
-.IP \fB${#\fP\fIname\fP\fB}\fP
-The number of positional parameters if \fIname\fP is \fB*\fP, \fB@\fP or
-is not specified,
-or the length of the string value of parameter \fIname\fP.
-.\"}}}
-.\"{{{ ${#name[*]}, ${#name[@]}
-.IP "\fB${#\fP\fIname\fP\fB[*]}\fP, \fB${#\fP\fIname\fP\fB[@]}\fP"
-The number of elements in the array \fIname\fP.
-.\"}}}
-.\"{{{ ${name#pattern}, ${name##pattern}
-.IP "\fB${\fP\fIname\fP\fB#\fP\fIpattern\fP\fB}\fP, \fB${\fP\fIname\fP\fB##\fP\fIpattern\fP\fB}\fP"
-If \fIpattern\fP matches the beginning of the value of parameter \fIname\fP,
-the matched text is deleted from the result of substitution. A single
-\fB#\fP results in the shortest match, two \fB#\fP's results in the
-longest match.
-.\"}}}
-.\"{{{ ${name%pattern}, ${name%%pattern}
-.IP "\fB${\fP\fIname\fP\fB%\fP\fIpattern\fP\fB}\fP, \fB${\fP\fIname\fP\fB%%\fP\fIpattern\fP\fB}\fP"
-Like \fB${\fP..\fB#\fP..\fB}\fP substitution, but it deletes from the end of the
-value.
-.\"}}}
-.\"{{{ special shell parameters
-.PP
-The following special parameters are implicitly set by the shell and cannot be
-set directly using assignments:
-.\"{{{ !
-.IP \fB!\fP
-Process id of the last background process started. If no background
-processes have been started, the parameter is not set.
-.\"}}}
-.\"{{{ #
-.IP \fB#\fP
-The number of positional parameters (\fIi.e.\fP, \fB$1\fP, \fB$2\fP,
-\fIetc.\fP).
-.\"}}}
-.\"{{{ $
-.IP \fB$\fP
-The process ID of the shell, or the PID of the original shell if
-it is a subshell.
-.\"}}}
-.\"{{{ -
-.IP \fB\-\fP
-The concatenation of the current single letter options
-(see \fBset\fP command below for list of options).
-.\"}}}
-.\"{{{ ?
-.IP \fB?\fP
-The exit status of the last non-asynchronous command executed.
-If the last command was killed by a signal, \fB$?\fP is set to 128 plus
-the signal number.
-.\"}}}
-.\"{{{ 0
-.IP "\fB0\fP"
-The name the shell was invoked with (\fIi.e.\fP, \fBargv[0]\fP), or the
-\fBcommand-name\fP if it was invoked with the \fB\-c\fP option and the
-\fBcommand-name\fP was supplied, or the \fIfile\fP argument, if it was
-supplied.
-If the \fBposix\fP option is not set, \fB$0\fP is the name of the current
-function or script.
-.\"}}}
-.\"{{{ 1-9
-.IP "\fB1\fP ... \fB9\fP"
-The first nine positional parameters that were supplied to the shell,
-function or \fB.\fP-script.
-Further positional parameters may be accessed using
-\fB${\fP\fInumber\fP\fB}\fP.
-.\"}}}
-.\"{{{ *
-.IP \fB*\fP
-All positional parameters (except parameter 0),
-\fIi.e.\fP, \fB$1 $2 $3\fP....
-If used outside of double quotes, parameters are separate words
-(which are subjected to word splitting); if used within double quotes,
-parameters are separated by the first character of the \fBIFS\fP parameter
-(or the empty string if \fBIFS\fP is null).
-.\"}}}
-.\"{{{ @
-.IP \fB@\fP
-Same as \fB$*\fP, unless it is used inside double quotes, in which case
-a separate word is generated for each positional parameter \- if there
-are no positional parameters, no word is generated ("$@" can be used
-to access arguments, verbatim, without loosing null arguments or
-splitting arguments with spaces).
-.\"}}}
-.\"}}}
-.\"{{{ general shell parameters
-.PP
-The following parameters are set and/or used by the shell:
-.\"{{{ _
-.IP "\fB_\fP \fI(underscore)\fP"
-In interactive use, this parameter is set to the last word of the
-previous command. When a command is executed, this parameter is set to
-the full path of the command and is placed in the command's environment.
-When \fBMAILPATH\fP messages are evaluated, this parameter contains
-the name of the file that changed (see \fBMAILPATH\fP parameter below).
-.\"}}}
-.\"{{{ CDPATH
-.IP \fBCDPATH\fP
-Search path for the \fBcd\fP built-in command. Works the same way as
-\fBPATH\fP for those directories not beginning with \fB/\fP in \fBcd\fP
-commands.
-Note that if CDPATH is set and does not contain \fB.\fP nor an empty path,
-the current directory is not searched.
-.\"}}}
-.\"{{{ COLUMNS
-.IP \fBCOLUMNS\fP
-Set to the number of columns on the terminal or window.
-Currently set to the \fBcols\fP value as reported by \fIstty\fP(1) if that
-value is non-zero.
-This parameter is used by the interactive line editing modes, and by
-\fBselect\fP, \fBset \-o\fP and \fBkill \-l\fP commands
-to format information in columns.
-.\"}}}
-.\"{{{ EDITOR
-.IP \fBEDITOR\fP
-If the \fBVISUAL\fP parameter is not set, this parameter controls the
-command line editing mode for interactive shells.
-See \fBVISUAL\fP parameter below for how this works.
-.\"}}}
-.\"{{{ ENV
-.IP \fBENV\fP
-If this parameter is found to be set after any profile files are
-executed, the expanded value is used as a shell start-up file. It
-typically contains function and alias definitions.
-.\"}}}
-.\"{{{ ERRNO
-.IP \fBERRNO\fP
-Integer value of the shell's errno variable \(em indicates the reason
-the last system call failed.
-.\" todo: ERRNO variable
-.sp
-Not implemented yet.
-.\"}}}
-.\"{{{ EXECSHELL
-.IP \fBEXECSHELL\fP
-If set, this parameter is assumed to contain the shell that is to be
-used to execute commands that \fIexecve\fP(2) fails to execute and
-which do not start with a `\fB#!\fP \fIshell\fP' sequence.
-.\"}}}
-.\"{{{ FCEDIT
-.IP \fBFCEDIT\fP
-The editor used by the \fBfc\fP command (see below).
-.\"}}}
-.\"{{{ FPATH
-.IP \fBFPATH\fP
-Like \fBPATH\fP, but used when an undefined function is executed to locate
-the file defining the function.
-It is also searched when a command can't be found using \fBPATH\fP.
-See Functions below for more information.
-.\"}}}
-.\"{{{ HISTFILE
-.IP \fBHISTFILE\fP
-The name of the file used to store history.
-When assigned to, history is loaded from the specified file.
-Also, several invocations of the
-shell running on the same machine will share history if their
-\fBHISTFILE\fP parameters all point at the same file.
-.br
-NOTE: if HISTFILE isn't set, no history file is used. This is
-different from the original Korn shell, which uses \fB$HOME/.sh_history\fP;
-in future, pdksh may also use a default history file.
-.\"}}}
-.\"{{{ HISTSIZE
-.IP \fBHISTSIZE\fP
-The number of commands normally stored for history, default 128.
-.\"}}}
-.\"{{{ HOME
-.IP \fBHOME\fP
-The default directory for the \fBcd\fP command and the value
-substituted for an unqualified \fB~\fP (see Tilde Expansion below).
-.\"}}}
-.\"{{{ IFS
-.IP \fBIFS\fP
-Internal field separator, used during substitution and by the \fBread\fP
-command, to split values into distinct arguments; normally set to
-space, tab and newline. See Substitution above for details.
-.br
-\fBNote:\fP this parameter is not imported from the environment
-when the shell is started.
-.\"}}}
-.\"{{{ KSH_VERSION
-.IP \fBKSH_VERSION\fP
-The version of shell and the date the version was created (readonly).
-See also the version commands in Emacs Interactive Input Line Editing
-and Vi Interactive Input Line Editing, below.
-.\"}}}
-.\"{{{ SH_VERSION
-.\"}}}
-.\"{{{ LINENO
-.IP \fBLINENO\fP
-The line number of the function or shell script that is currently being
-executed.
-.\" todo: LINENO variable
-.sp
-Not implemented yet.
-.\"}}}
-.\"{{{ LINES
-.IP \fBLINES\fP
-Set to the number of lines on the terminal or window.
-.\"Currently set to the \fBrows\fP value as reported by \fIstty\fP(1) if that
-.\"value is non-zero.
-.\" todo: LINES variable
-.sp
-Not implemented yet.
-.\"}}}
-.\"{{{ MAIL
-.IP \fBMAIL\fP
-If set, the user will be informed of the arrival of mail in the named
-file. This parameter is ignored if the \fBMAILPATH\fP parameter is set.
-.\"}}}
-.\"{{{ MAILCHECK
-.IP \fBMAILCHECK\fP
-How often, in seconds, the shell will check for mail in the file(s)
-specified by \fBMAIL\fP or \fBMAILPATH\fP. If 0, the shell checks
-before each prompt. The default is 600 (10 minutes).
-.\"}}}
-.\"{{{ MAILPATH
-.IP \fBMAILPATH\fP
-A list of files to be checked for mail. The list is colon separated,
-and each file may be followed by a \fB?\fP and a message to be printed
-if new mail has arrived. Command, parameter and arithmetic substitution is
-performed on the message, and, during substitution, the parameter \fB$_\fP
-contains the name of the file.
-The default message is \fByou have mail in $_\fP.
-.\"}}}
-.\"{{{ OLDPWD
-.IP \fBOLDPWD\fP
-The previous working directory.
-Unset if \fBcd\fP has not successfully changed directories since the
-shell started, or if the shell doesn't know where it is.
-.\"}}}
-.\"{{{ OPTARG
-.IP \fBOPTARG\fP
-When using \fBgetopts\fP, it contains the argument for a parsed option,
-if it requires one.
-.\"}}}
-.\"{{{ OPTIND
-.IP \fBOPTIND\fP
-The index of the last argument processed when using \fBgetopts\fP.
-Assigning 1 to this parameter causes \fBgetopts\fP to
-process arguments from the beginning the next time it is invoked.
-.\"}}}
-.\"{{{ PATH
-.IP \fBPATH\fP
-A colon separated list of directories that are searched when looking
-for commands and \fB.\fP'd files.
-An empty string resulting from a leading or trailing colon, or two adjacent
-colons is treated as a `.', the current directory.
-.\"}}}
-.\"{{{ POSIXLY_CORRECT
-.IP \fBPOSIXLY_CORRECT\fP
-If set, this parameter causes the \fBposix\fP option to be enabled.
-See POSIX Mode below.
-.\"}}}
-.\"{{{ PPID
-.IP \fBPPID\fP
-The process ID of the shell's parent (readonly).
-.\"}}}
-.\"{{{ PS1
-.IP \fBPS1\fP
-\fBPS1\fP is the primary prompt for interactive shells.
-Parameter, command and arithmetic substitutions are performed, and
-\fB!\fP is replaced with the current command number (see \fBfc\fP
-command below). A literal ! can be put in the prompt by placing !! in PS1.
-Note that since the command line editors try to figure out how long the
-prompt is (so they know how far it is to edge of the screen),
-escape codes in the prompt tend to mess things up.
-You can tell the shell not to count certain sequences (such as escape codes)
-by prefixing your prompt with a non-printing character (such as control-A)
-followed by a carriage return and then delimiting the escape codes with
-this non-printing character.
-If you don't have any non-printing characters, you're out of luck...
-BTW, don't blame me for this hack; it's in the original ksh.
-Default is `\fB$\ \fP' for non-root users, `\fB#\ \fP' for root..
-.\"}}}
-.\"{{{ PS2
-.IP \fBPS2\fP
-Secondary prompt string, by default `\fB>\fP ', used when more input is
-needed to complete a command.
-.\"}}}
-.\"{{{ PS3
-.IP \fBPS3\fP
-Prompt used by \fBselect\fP statement when reading a menu selection.
-Default is `\fB#?\ \fP'.
-.\"}}}
-.\"{{{ PS4
-.IP \fBPS4\fP
-Used to prefix commands that are printed during execution tracing
-(see \fBset \-x\fP command below).
-Parameter, command and arithmetic substitutions are performed
-before it is printed.
-Default is `\fB+\ \fP'.
-.\"}}}
-.\"{{{ PWD
-.IP \fBPWD\fP
-The current working directory. Maybe unset or null if shell doesn't
-know where it is.
-.\"}}}
-.\"{{{ RANDOM
-.IP \fBRANDOM\fP
-A simple random number generator. Every time \fBRANDOM\fP is
-referenced, it is assigned the next number in a random number series.
-The point in the series can be set by assigning a number to
-\fBRANDOM\fP (see \fIrand\fP(3)).
-.\"}}}
-.\"{{{ REPLY
-.IP \fBREPLY\fP
-Default parameter for the \fBread\fP command if no names are given.
-Also used in \fBselect\fP loops to store the value that is read from
-standard input.
-.\"}}}
-.\"{{{ SECONDS
-.IP \fBSECONDS\fP
-The number of seconds since the shell started or, if the parameter has been
-assigned an integer value, the number of seconds since the assignment plus
-the value that was assigned.
-.\"}}}
-.\"{{{ TMOUT
-.IP \fBTMOUT\fP
-If set to a positive integer in an interactive shell, it specifies
-the maximum number of seconds the shell will wait for input after
-printing the primary prompt (\fBPS1\fP). If the time is exceeded, the
-shell exits.
-.\"}}}
-.\"{{{ TMPDIR
-.IP \fBTMPDIR\fP
-The directory shell temporary files are created in. If this parameter
-is not set, or does not contain the absolute path of a writable
-directory, temporary files are created in \fB/tmp\fP.
-.\"}}}
-.\"{{{ VISUAL
-.IP \fBVISUAL\fP
-If set, this parameter controls the command line editing mode for
-interactive shells. If the last component of the path specified in this
-parameter contains the string \fBvi\fP, \fBemacs\fP or \fBgmacs\fP, the
-vi, emacs or gmacs (Gosling emacs) editing mode is enabled, respectively.
-.\"}}}
-.\"}}}
-.\"}}}
-.\"{{{ Tilde Expansion
-.SS "Tilde Expansion"
-Tilde expansion, which is done in parallel with parameter substitution,
-is done on words starting with an unquoted \fB~\fP. The characters
-following the tilde, up to the first \fB/\fP, if any, are assumed to be
-a login name. If the login name is empty, \fB+\fP or \fB\-\fP, the
-value of the \fBHOME\fP, \fBPWD\fP, or \fBOLDPWD\fP parameter is
-substituted, respectively. Otherwise, the password file is searched for
-the login name, and the tilde expression is substituted with the
-user's home directory. If the login name is not found in the password
-file or if any quoting or parameter substitution occurs in the login name,
-no substitution is performed.
-.PP
-In parameter assignments (those preceding a simple-command or those
-occurring in the arguments of \fBalias\fP, \fBexport\fP, \fBreadonly\fP,
-and \fBtypeset\fP), tilde expansion is done after any unquoted colon
-(\fB:\fP), and login names are also delimited by colons.
-.PP
-The home directory of previously expanded login names are cached and
-re-used. The \fBalias \-d\fP command may be used to list, change and
-add to this cache (\fIe.g.\fP, `alias \-d fac=/usr/local/facilities; cd
-~fac/bin').
-.\"}}}
-.\"{{{ Brace Expansion
-.SS "Brace Expansion (alternation)"
-Brace expressions, which take the form
-.RS
-\fIprefix\fP\fB{\fP\fIstr\fP1\fB,\fP...\fB,\fP\fIstr\fPN\fB}\fP\fIsuffix\fP
-.RE
-are expanded to N words, each of which is the concatenation of
-\fIprefix\fP, \fIstr\fPi and \fIsuffix\fP
-(\fIe.g.\fP, `a{c,b{X,Y},d}e' expands to four word: ace, abXe, abYe, and ade).
-As noted in the example, brace expressions can be nested and the resulting
-words are not sorted.
-Brace expressions must contain an unquoted comma (\fB,\fP) for expansion
-to occur (\fIi.e.\fP, \fB{}\fP and \fB{foo}\fP are not expanded).
-Brace expansion is carried out after parameter substitution and before
-file name generation.
-.\"}}}
-.\"{{{ File Name Patterns
-.SS "File Name Patterns"
-.PP
-A file name pattern is a word containing one or more unquoted \fB?\fP or
-\fB*\fP characters or \fB[\fP..\fB]\fP sequences. Once brace expansion has
-been performed, the shell replaces file name patterns with the sorted names
-of all the files that match the pattern (if no files match, the word is
-left unchanged). The pattern elements have the following meaning:
-.IP \fB?\fP
-matches any single character.
-.IP \fB*\fP
-matches any sequence of characters.
-.IP \fB[\fP..\fB]\fP
-matches any of the characters inside the brackets. Ranges of characters
-can be specified by separating two characters by a \fB\-\fP, \fIe.g.\fP,
-\fB[a0\-9]\fP matches the letter \fBa\fP or any digit.
-In order to represent itself, a
-\fB\-\fP must either be quoted or the first or last character in the character
-list. Similarly, a \fB]\fP must be quoted or the first character in the list
-if it is represent itself instead of the end of the list. Also, a \fB!\fP
-appearing at the start of the list has special meaning (see below), so to
-represent itself it must be quoted or appear later in the list.
-.IP \fB[!\fP..\fB]\fP
-like \fB[\fP..\fB]\fP, except it matches any character not inside the brackets.
-.IP "\fB*(\fP\fIpattern\fP\fB|\fP ... \fP|\fP\fIpattern\fP\fB)\fP"
-matches any string of characters that matches zero or more occurances
-of the specified patterns.
-Example: the pattern \fB*(foo|bar)\fP matches the strings
-`', `foo', `bar', `foobarfoo', \fIetc.\fP.
-.IP "\fB+(\fP\fIpattern\fP\fB|\fP ... \fP|\fP\fIpattern\fP\fB)\fP"
-matches any string of characters that matches one or more occurances
-of the specified patterns.
-Example: the pattern \fB+(foo|bar)\fP matches the strings
-`foo', `bar', `foobarfoo', \fIetc.\fP.
-.IP "\fB?(\fP\fIpattern\fP\fB|\fP ... \fP|\fP\fIpattern\fP\fB)\fP"
-matches the empty string or a string that matches one of the
-specified patterns.
-Example: the pattern \fB?(foo|bar)\fP only matches the strings
-`', `foo' and `bar'.
-.IP "\fB@(\fP\fIpattern\fP\fB|\fP ... \fP|\fP\fIpattern\fP\fB)\fP"
-matches a string that matches one of the
-specified patterns.
-Example: the pattern \fB@(foo|bar)\fP only matches the strings
-`foo' and `bar'.
-.IP "\fB!(\fP\fIpattern\fP\fB|\fP ... \fP|\fP\fIpattern\fP\fB)\fP"
-matches any string that does not match one of the specified
-patterns.
-Examples: the pattern \fB!(foo|bar)\fP matches all strings except
-`foo' and `bar'; the pattern \fB!(*)\fP matches no strings;
-the pattern \fB!(?)*\fP matches all strings (think about it).
-.PP
-Note that pdksh currently never matches \fB.\fP and \fB..\fP, but the original
-ksh, Bourne sh and bash do, so this may have to change (too bad).
-.PP
-Note that none of the above pattern elements match either a period (\fB.\fP)
-at the start of a file name or a slash (\fB/\fP), even if they are explicitly
-used in a \fB[\fP..\fB]\fP sequence; also, the names \fB.\fP and \fB..\fP
-are never matched, even by the pattern \fB.*\fP.
-.PP
-If the \fBmarkdirs\fP option is set, any directories that result from
-file name generation are marked with a trailing \fB/\fP.
-.PP
-.\" todo: implement this ([[:alpha:]], \fIetc.\fP)
-The POSIX character classes (\fIi.e.\fP,
-\fB[:\fP\fIclass-name\fP\fB:]\fP inside a \fB[\fP..\fB]\fP expression)
-are not yet implemented.
-.\"}}}
-.\"{{{ Input/Output Redirection
-.SS "Input/Output Redirection"
-When a command is executed, its standard input, standard output and
-standard error (file descriptors 0, 1 and 2, respectively) are normally
-inherited from the shell.
-Three exceptions to this are commands in pipelines, for which standard input
-and/or standard output are those set up by the pipeline, asynchronous commands
-created when job control is disabled, for which standard input is initially
-set to be from \fB/dev/null\fP, and commands for which any of the following
-redirections have been specified:
-.IP "\fB>\fP \fIfile\fP"
-standard output is redirected to \fIfile\fP. If \fIfile\fP does not exist,
-it is created; if it does exist, is a regular file and the \fBnoclobber\fP
-option is set, an error occurs, otherwise the file is truncated.
-Note that this means the command \fIcmd < foo > foo\fP will open
-\fIfoo\fP for reading and then truncate it when it opens it for writing,
-before \fIcmd\fP gets a chance to actually read \fIfoo\fP.
-.IP "\fB>|\fP \fIfile\fP"
-same as \fB>\fP, except the file is truncated, even if the \fBnoclobber\fP
-option is set.
-.IP "\fB>>\fP \fIfile\fP"
-same as \fB>\fP, except the file an existing file is appended to instead
-of being truncated. Also, the file is opened in append mode, so writes
-always go to the end of the file (see \fIopen\fP(2)).
-.IP "\fB<\fP \fIfile\fP"
-standard input is redirected from \fIfile\fP, which is opened for reading.
-.IP "\fB<>\fP \fIfile\fP"
-same as \fB<\fP, except the file is opened for reading and writing.
-.IP "\fB<<\fP \fImarker\fP"
-after reading the command line containing this kind of redirection (called a
-here document), the shell copies lines from the command source into a temporary
-file until a line matching \fImarker\fP is read.
-When the command is executed, standard input is redirected from the temporary
-file.
-If \fImarker\fP contains no quoted characters, the contents of the
-temporary file are processed as if enclosed in double quotes each time
-the command is executed, so parameter, command and arithmetic substitutions
-are performed, along with backslash (\fB\e\fP) escapes for
-\fB$\fP, \fB`\fP, \fB\e\fP and \fB\enewline\fP.
-If multiple here documents are used on the same command line, they are
-saved in order.
-.IP "\fB<<-\fP \fImarker\fP"
-same as \fB<<\fP, except leading tabs are stripped from lines in the
-here document.
-.IP "\fB<&\fP \fIfd\fP"
-standard input is duplicated from file descriptor \fIfd\fP.
-\fIfd\fP can be a single digit, indicating the number of an existing
-file descriptor, the letter \fBp\fP, indicating the file descriptor
-associated with the output of the current co-process, or
-the character \fB\-\fP, indicating standard input is to be closed.
-.IP "\fB>&\fP \fIfd\fP"
-same as \fB<&\fP, except the operation is done on standard output.
-.PP
-In any of the above redirections, the file descriptor that is redirected
-(\fIi.e.\fP, standard input or standard output) can be explicitly given by
-preceding the redirection with a single digit.
-Parameter, command and arithmetic substitutions, tilde substitutions and
-file name generation are all performed on the \fIfile\fP, \fImarker\fP and
-\fIfd\fP arguments of redirections.
-Note however, that the results of any file name generation are only used
-if a single file is matched; if multiple files match, the word with the
-unexpanded file name generation characters is used.
-Note that in restricted shells, redirections which can create files cannot
-be used.
-.PP
-For simple-commands, redirections may appear anywhere in the command, for
-compound-commands (\fBif\fP statements, \fIetc.\fP), any redirections must
-appear at the end.
-Redirections are processed after pipelines are created and in the order they
-are given, so
-.RS
-\fBcat /foo/bar 2>&1 > /dev/null | cat \-n\fP
-.RE
-will print an error with a line number prepended to it.
-.\"}}}
-.\"{{{ Arithmetic Expressions
-.SS "Arithmetic Expressions"
-Integer arithmetic expressions can be used
-with the \fBlet\fP command,
-inside \fB$((\fP..\fB))\fP expressions,
-inside array references (\fIe.g.\fP, \fIname\fP\fB[\fP\fIexpr\fP\fB]\fP),
-as numeric arguments to the \fBtest\fP command,
-and as the value of an assignment to an integer parameter.
-.PP
-Expression may contain alpha-numeric parameter identifiers, array
-references, and integer constants and may be combined with the
-following C operators (listed and grouped in increasing order of precedence).
-.TP
-Unary operators:
-\fB+ \- ! ~ ++ --\fP
-.TP
-Binary operators:
-\fB,\fP
-.br
-\fB= *= /= %= += \-= <<= >>= &= ^= |=\fP
-.br
-\fB||\fP
-.br
-\fB&&\fP
-.br
-\fB|\fP
-.br
-\fB^\fP
-.br
-\fB&\fP
-.br
-\fB== !=\fP
-.br
-\fB< <= >= >\fP
-.br
-\fB<< >>\fP
-.br
-\fB+ \-\fP
-.br
-\fB* / %\fP
-.TP
-Ternary operator:
-\fB?:\fP (precedence is immediately higher than assignment)
-.TP
-Grouping operators:
-\fB( )\fP
-.PP
-Integer constants may be specified with arbitrary bases using the notation
-\fIbase\fP\fB#\fP\fInumber\fP, where \fIbase\fP is a decimal integer specifying
-the base, and \fInumber\fP is a number in the specified base.
-.LP
-The operators are evaluated as follows:
-.RS
-.IP "unary \fB+\fP"
-result is the argument (included for completeness).
-.IP "unary \fB\-\fP"
-negation.
-.IP "\fB!\fP"
-logical not; the result is 1 if argument is zero, 0 if not.
-.IP "\fB~\fP"
-arithmetic (bit-wise) not.
-.IP "\fB++\fP"
-increment; must be applied to a parameter (not a literal or other
-expression) - the parameter is incremented by 1.
-When used as a prefix operator, the result is the incremented value of
-the parameter, when used as a postfix operator, the result is the
-original value of the parameter.
-.IP "\fB++\fP"
-similar to \fB++\fP, except the paramter is decremented by 1.
-.IP "\fB,\fP"
-seperates two arithmetic expressions; the left hand side is evaluated first,
-then the right. The result is value of the expression on the right hand side.
-.IP "\fB=\fP"
-assignment; variable on the left is set to the value on the right.
-.IP "\fB*= /= %= += \-= <<= >>= &= ^= |=\fP"
-assignment operators; \fI<var> <op>\fP\fB=\fP \fI<expr>\fP is the same as
-\fI<var>\fP \fB=\fP \fI<var> <op>\fP \fB(\fP \fI<expr>\fP \fB)\fP.
-.IP "\fB||\fP"
-logical or; the result is 1 if either argument is non-zero, 0 if not.
-The right argument is evaluated only if the left argument is zero.
-.IP "\fB&&\fP"
-logical and; the result is 1 if both arguments are non-zero, 0 if not.
-The right argument is evaluated only if the left argument is non-zero.
-.IP "\fB|\fP"
-arithmetic (bit-wise) or.
-.IP "\fB^\fP"
-arithmetic (bit-wise) exclusive-or.
-.IP "\fB&\fP"
-arithmetic (bit-wise) and.
-.IP "\fB==\fP"
-equal; the result is 1 if both arguments are equal, 0 if not.
-.IP "\fB!=\fP"
-not equal; the result is 0 if both arguments are equal, 1 if not.
-.IP "\fB<\fP"
-less than; the result is 1 if the left argument is less than the right,
-0 if not.
-.IP "\fB<= >= >\fP"
-less than or equal, greater than or equal, greater than. See <.
-.IP "\fB<< >>\fP"
-shift left (right); the result is the left argument with its bits shifted
-left (right) by the amount given in the right argument.
-.IP "\fB+ - * /\fP"
-addition, subtraction, multiplication, and division.
-.IP "\fB%\fP"
-remainder; the result is the remainder of the division of the left argument
-by the right. The sign of the result is unspecified if either argument
-is negative.
-.IP "\fI<arg1>\fP \fB?\fP \fI<arg2>\fP \fB:\fP \fI<arg3>\fP"
-if \fI<arg1>\fP is non-zero, the result is \fI<arg2>\fP,
-otherwise \fI<arg3>\fP.
-.RE
-.\"}}}
-.\"{{{ Co-Processes
-.SS "Co-Processes"
-A co-process, which is a pipeline created with the \fB|&\fP operator,
-is an asynchronous process that the shell can both write to
-(using \fBprint \-p\fP) and read from (using \fBread \-p\fP).
-The input and output of the co-process can also be manipulated
-using \fB>&p\fP and \fB<&p\fP redirections, respectively.
-Once a co-process has been started, another can't be started until
-the co-process exits, or until the co-process input has been redirected using
-an \fBexec \fP\fIn\fP\fB>&p\fP redirection.
-If a co-process's input is redirected in this way, the next
-co-process to be started will share the output with the first co-process,
-unless the output of the initial co-process has been redirected using an
-\fBexec \fP\fIn\fP\fB<&p\fP redirection.
-.PP
-Some notes concerning co-processes:
-.nr P2 \n(PD
-.nr PD 0
-.IP \ \ \(bu
-the only way to close the co-process input (so the co-process reads
-an end-of-file) is to redirect the input to a numbered file descriptor
-and then close that file descriptor (\fIe.g.\fP, \fBexec 3>&p;exec 3>&-\fP).
-.IP \ \ \(bu
-in order for co-processes to share a common output, the shell must keep
-the write portion of the output pipe open.
-This means that end of file will not be detected until all co-processes
-sharing the co-process output have exited (when they all exit, the shell
-closes its copy of the pipe).
-This can be avoided by redirecting the output to a numbered
-file descriptor (as this also causes the shell to close its copy).
-Note that this behaviour is slightly different from the original Korn shell
-which closes its copy of the write portion of the co-processs output when the
-most recently started co-process (instead of when all sharing co-processes)
-exits.
-.IP \ \ \(bu
-\fBprint \-p\fP will ignore SIGPIPE signals during writes
-if the signal is not being trapped or ignored; the same is not true if
-the co-process input has been duplicated to another file descriptor and
-\fBprint \-u\fP\fIn\fP is used.
-.nr PD \n(P2
-.\"}}}
-.\"{{{ Functions
-.SS "Functions"
-Functions are defined using either Korn shell \fBfunction\fP \fIname\fP
-syntax or the Bourne/POSIX shell \fIname\fP\fB()\fP syntax
-(see below for the difference between the two forms).
-Functions are like \fB.\fP-scripts in that they are executed in
-the current environment, however, unlike \fB.\fP-scripts, shell arguments
-(\fIi.e.\fP, positional parameters, \fB$1\fP, \fIetc.\fP) are never visible
-inside them.
-When the shell is determining the location of a command, functions are
-searched after special built-in commands, and before regular and non-regular
-built-ins, and before the \fBPATH\fP is searched.
-.PP
-An existing function may be deleted using \fBunset \-f\fP \fIfunction-name\fP.
-A list of functions can be obtained using \fBtypeset +f\fP and the
-function definitions can be listed using \fBtypeset \-f\fP.
-\fBautoload\fP (which is an alias for \fBtypeset \-fu\fP) may be used to
-create undefined functions; when an undefined function is executed, the
-shell searches the path specified in the \fBFPATH\fP parameter for a file
-with the same name as the function, which, if found is read and executed.
-If after executing the file, the named function is found to be defined, the
-function is executed, otherwise, the normal command search is continued
-(\fIi.e.\fP, the shell searches the regular built-in command table
-and \fBPATH\fP).
-Note that if a command is not found using \fBPATH\fP, an attempt is
-made to autoload a function using \fBFPATH\fP (this is an undocumented
-feature of the original Korn shell).
-.PP
-Functions can have two attributes, trace and export, which can be set
-with \fBtypeset \-ft\fP and \fBtypeset \-fx\fP, respectively.
-When a traced function is executed, the shell's \fBxtrace\fP option is turned
-on for the functions duration, otherwise the \fBxtrace\fP option is turned off.
-The export attribute of functions is currently not used. In the original
-Korn shell, exported functions are visible to shell scripts that are executed.
-.PP
-Since functions are executed in the current shell environment, parameter
-assignments made inside functions are visible after the function completes.
-If this is not the desired effect, the \fBtypeset\fP command can be used
-inside a function to create a local parameter.
-Note that special parameters (\fIe.g.\fP, \fB$$\fP, \fB$!\fP) can't be
-scoped in this way.
-.PP
-The exit status of a function is that of the last command executed in
-the function.
-A function can be made to finish immediately using the \fBreturn\fP command;
-this may also be used to explicitly specify the exit status.
-.PP
-Functions defined with the \fBfunction\fP reserved word are
-treated differently in the following ways from functions defined with
-the \fB()\fP notation:
-.nr P2 \n(PD
-.nr PD 0
-.IP \ \ \(bu
-the \fB$0\fP parameter is set to the name of the function
-(Bourne-style functions leave \fB$0\fP untouched).
-.IP \ \ \(bu
-parameter assignments preceeding function calls are not kept in
-the shell environment
-(executing Bourne-style functions will keep assignments).
-.nr PD \n(P2
-In the future, the following differences will also be added:
-.nr P2 \n(PD
-.nr PD 0
-.IP \ \ \(bu
-A separate trap/signal environment will be used during the execution of
-functions.
-This will mean that traps set inside a function will not affect the shell's
-traps and signals that are not ignored in the shell (but may be trapped) will
-have their default effect in a function.
-.IP \ \ \(bu
-The EXIT trap, if set in a function, will be executed after the function
-returns.
-.nr PD \n(P2
-.\"}}}
-.\"{{{ POSIX mode
-.SS "POSIX Mode"
-The shell is intended to be POSIX compliant, however, in some cases, POSIX
-behaviour is contrary either to the original Korn shell behaviour or to
-user convenience.
-How the shell behaves in these cases is determined by the state of
-the posix option (\fBset \-o posix\fP) \(em if it is on, the POSIX behaviour
-is followed, otherwise it is not.
-The \fBposix\fP option is set automatically when the shell starts up
-if the environment contains the \fBPOSIXLY_CORRECT\fP parameter.
-(The shell can also be compiled so that it is in POSIX mode by default,
-however this is usually not desirable).
-.PP
-The following is a list of things that are affected by the state of
-the \fBposix\fP option:
-.nr P2 \n(PD
-.nr PD 0
-.IP \ \ \(bu
-\fB\e"\fP inside double quoted \fB`\fP..\fB`\fP command substitutions:
-in posix mode, the \fB\e"\fP is interpreted when the command is interpreted;
-in non-posix mode, the backslash is stripped before the command substitution
-is interpreted. For example, \fBecho "`echo \e"hi\e"`"\fP produces `"hi"' in
-posix mode, `hi' in non-posix mode. To avoid problems, use the \fB$(...\fP)
-form of command substitution.
-.IP \ \ \(bu
-\fBkill \-l\fP output: in posix mode, signal names are listed one a single line;
-in non-posix mode, signal numbers, names and descriptions are printed in
-columns.
-In future, a new option (\fB\-v\fP perhaps) will be added to distinguish
-the two behaviours.
-.IP \ \ \(bu
-\fBfg\fP exit status: in posix mode, the exit status is 0 if no errors occur;
-in non-posix mode, the exit status is that of the last foregrounded job.
-.IP \ \ \(bu
-\fBgetopts\fP: in posix mode, options must start with a \fB\-\fP; in non-posix
-mode, options can start with either \fB\-\fP or \fB+\fP.
-.IP \ \ \(bu
-brace expansion (also known as alternation): in posix mode, brace expansion
-is disabled; in non-posix mode, brace expansion enabled.
-Note that \fBset \-o posix\fP (or setting the \fBPOSIXLY_CORRECT\fP parameter)
-automatically turns the \fBbraceexpand\fP option off, however it can be
-explicitly turned on later.
-.IP \ \ \(bu
-\fBset \-\fP: in posix mode, this does not clear the \fBverbose\fP or
-\fBxtrace\fP options; in non-posix mode, it does.
-.IP \ \ \(bu
-\fBset\fP exit status: in posix mode, the exit status of set is 0
-if there are no errors; in non-posix mode, the exit status is that of
-any command substitutions performed in generating the set command.
-For example, `\fBset \-\- `false`; echo $?\fP' prints 0 in posix mode,
-1 in non-posix mode. This construct is used in most shell scripts that
-use the old \fIgetopt\fP(1) command.
-.IP \ \ \(bu
-argument expansion of \fBalias\fP, \fBexport\fP, \fBreadonly\fP, and
-\fBtypeset\fP commands: in posix mode, normal argument expansion done;
-in non-posix mode, field splitting, file globing, brace expansion and
-(normal) tilde expansion are turned off, and assignment tilde expansion
-is turned on.
-.IP \ \ \(bu
-signal specification: in posix mode, signals can be specified as digits only
-if signal numbers match POSIX values (\fIi.e.\fP, HUP=1, INT=2, QUIT=3, ABRT=6,
-KILL=9, ALRM=14, and TERM=15); in non-posix mode, signals can be always digits.
-.IP \ \ \(bu
-alias expansion: in posix mode, alias expansion is only carried out when
-reading command words; in non-posix mode, alias expansion is carried out
-on any word following an alias that ended in a space.
-For example, the following for loop
-.RS
-.ft B
-alias a='for ' i='j'
-.br
-a i in 1 2; do echo i=$i j=$j; done
-.ft P
-.RE
-uses parameter \fBi\fP in posix mode, \fBj\fP in non-posix mode.
-.nr PD \n(P2
-.\"}}}
-.\"{{{ Command Execution (built-in commands)
-.SS "Command Execution"
-After evaluation of command line arguments, redirections and parameter
-assignments, the type of command is determined: a special built-in,
-a function, a regular built-in or the name of a file to execute found
-using the \fBPATH\fP parameter.
-The checks are made in the above order.
-Special built-in commands differ from other commands in that
-the \fBPATH\fP parameter is not used to find them, an error
-during their execution can cause a non-interactive shell to exit and
-parameter assignments that are specified before the command are
-kept after the command completes.
-Just to confuse things, if the posix option is turned off (see \fBset\fP
-command below) some special commands are very special in that
-no field splitting, file globing, brace expansion nor tilde expansion
-is preformed on arguments that look like assignments.
-Regular built-in commands are different only in that the \fBPATH\fP
-parameter is not used to find them.
-.PP
-The original ksh and POSIX differ somewhat in which commands are considered
-special or regular:
-.IP "POSIX special commands"
-.TS
-lw(8m)fB lw(8m)fB lw(8m)fB lw(8m)fB lw(8m)fB .
-\&. continue exit return trap
-: eval export set unset
-break exec readonly shift
-.TE
-.IP "Additional ksh special commands"
-.TS
-lw(8m)fB lw(8m)fB lw(8m)fB lw(8m)fB lw(8m)fB .
-builtin times typeset
-.TE
-.IP "Very special commands (non-posix mode)"
-.TS
-lw(8m)fB lw(8m)fB lw(8m)fB lw(8m)fB lw(8m)fB .
-alias readonly set typeset
-.TE
-.IP "POSIX regular commands"
-.TS
-lw(8m)fB lw(8m)fB lw(8m)fB lw(8m)fB lw(8m)fB .
-alias command fg kill umask
-bg false getopts read unalias
-cd fc jobs true wait
-.TE
-.IP "Additional ksh regular commands"
-.TS
-lw(8m)fB lw(8m)fB lw(8m)fB lw(8m)fB lw(8m)fB .
-[ let pwd ulimit
-echo print test whence
-.TE
-.PP
-In the future, the additional ksh special and regular commands may
-be treated differently from the POSIX special and regular commands.
-.PP
-Once the type of the command has been determined, any command line parameter
-assignments are performed and exported for the duration of the command.
-.PP
-The following describes the special and regular built-in commands:
-.\"{{{ . file [ arg1 ... ]
-.IP "\fB\&.\fP \fIfile\fP [\fIarg1\fP ...]"
-Execute the commands in \fIfile\fP in the current environment.
-The file is searched for in the directories of \fBPATH\fP.
-If arguments are given, the positional parameters may be used to
-access them while \fIfile\fP is being executed.
-If no arguments are given, the positional parameters are those of the
-environment the command is used in.
-.\"}}}
-.\"{{{ : [ ... ]
-.IP "\fB:\fP [ ... ]"
-The null command.
-Exit status is set to zero.
-.\"}}}
-.\"{{{ alias [ -d | -t [ -r ] ] [-x] [name1[=value1] ...]
-.IP "\fBalias\fP [ \fB\-d\fP | \fB\-t\fP [\fB\-r\fP] ] [\fB\-x\fP] [\fIname1\fP[\fB=\fP\fIvalue1\fP] ...]"
-Without arguments, \fBalias\fP lists all aliases and their values. For
-any name without a value, its value is listed. Any name with a value
-defines an alias (see Aliases above).
-.sp
-The \fB\-x\fP option sets the export attribute of an alias, or, if no
-names are given, lists the aliases with the export attribute
-(exporting an alias currently has no affect).
-.sp
-The \fB\-t\fP option indicates that tracked aliases are to be listed/set
-(values specified on the command line are ignored for tracked aliases).
-The \fB\-r\fP option indicates that all tracked aliases are to be reset.
-.sp
-The \fB\-d\fP causes directory aliases, which are used in tilde expansion,
-to be listed or set (see Tilde Expansion above).
-.\"}}}
-.\"{{{ bg [job ...]
-.IP "\fBbg\fP [\fIjob\fP ...]"
-Resume the specified stopped job(s) in the background.
-If no jobs are specified, \fB%+\fP is assumed.
-This command is only available on systems which support job control.
-See Job Control below for more information.
-.\"}}}
-.\"{{{ bind [-l] [-m] [key[=editing-command] ...]
-.IP "\fBbind\fP [\fB\-m\fP] [\fIkey\fP[\fB=\fP\fIediting-command\fP] ...]"
-Set or view the current emacs command editing key bindings/macros.
-See Emacs Interactive Input Line Editing below for a complete description.
-.\"}}}
-.\"{{{ break [level]
-.IP "\fBbreak\fP [\fIlevel\fP]"
-\fBbreak\fP exits the \fIlevel\fPth inner most for, select, until, or while
-loop.
-\fIlevel\fP defaults to 1.
-.\"}}}
-.\"{{{ builtin command [arg1 ...]
-.IP "\fBbuiltin\fP \fIcommand\fP [\fIarg1\fP ...]"
-Execute the built-in command \fIcommand\fP.
-.\"}}}
-.\"{{{ cd [-LP] [dir]
-.IP "\fBcd\fP [\fB\-LP\fP] [\fIdir\fP]"
-Set the working directory to \fIdir\fP. If the parameter \fBCDPATH\fP
-is set, it lists the search path for the directory containing
-\fIdir\fP. A null path means the current directory. If \fIdir\fP is
-missing, the home directory \fB$HOME\fP is used. If \fIdir\fP is
-\fB\-\fP, the previous working directory is used (see OLDPWD parameter).
-If \fB\-L\fP option (logical path) is used or if the \fBphysical\fP option
-(see \fBset\fP command below) isn't set, references to \fB..\fP in \fIdir\fP
-are relative to the path used get to the directory.
-If \fB\-P\fP option (physical path) is used or if the \fBphysical\fP option
-is set, \fB..\fP is relative to the filesystem directory tree.
-The \fBPWD\fP and \fBOLDPWD\fP parameters are updated to reflect the
-current and old wording directory, respectively.
-.\"}}}
-.\"{{{ cd [-LP] old new
-.IP "\fBcd\fP [\fB\-LP\fP] \fIold new\fP"
-The string \fInew\fP is substituted for \fIold\fP in the current
-directory, and the shell attempts to change to the new directory.
-.\"}}}
-.\"{{{ command [ -pvV ] cmd [arg1 ...]
-.IP "\fBcommand\fP [\fB\-pvV\fP] \fIcmd\fP [\fIarg1\fP ...]"
-If neither the \fB\-v\fP nor \fB\-V\fP options are given,
-\fIcmd\fP
-is executed exactly as if the \fBcommand\fP had not been specified,
-with two exceptions: first, \fIcmd\fP cannot be a shell function, and
-second, special built-in commands lose their specialness (\fIi.e.\fP,
-redirection and utility errors do not cause the shell to exit, and command
-assignments are not permanent).
-If the \fB\-p\fP option is given, a default search path is used instead of
-the current value of \fBPATH\fP (the actual value of the default path is
-system dependent: on POSIXish systems, it is the value returned by
-.ce
-\fBgetconf CS_PATH\fP
-).
-.sp
-If the \fB\-v\fP option is given, instead of executing \fIcmd\fP, information
-about what would be executed is given (and the same is done for
-\fIarg1\fP ...):
-for special and regular built-in commands and functions,
-their names are simply printed,
-for aliases, a command that defines them is printed,
-and for commands found by searching the \fBPATH\fP parameter,
-the full path of the command is printed.
-If no command is be found, (\fIi.e.\fP, the path search fails), nothing
-is printed and \fBcommand\fP exits with a non-zero status.
-The \fB\-V\fP option is like the \fB\-v\fP option, except it is more verbose.
-.\"}}}
-.\"{{{ continue [levels]
-.IP "\fBcontinue\fP [\fIlevels\fP]"
-\fBcontinue\fP jumps to the beginning of the \fIlevel\fPth inner most for,
-select, until, or while loop.
-\fIlevel\fP defaults to 1.
-.\"}}}
-.\"{{{ echo [-neE] [arg ...]
-.IP "\fBecho\fP [\fB\-neE\fP] [\fIarg\fP ...]"
-Prints its arguments (separated by spaces) followed by a newline, to
-standard out.
-The newline is suppressed if any of the arguments contain the backslash
-sequence \fB\ec\fP.
-See \fBprint\fP command below for a list of other backslash sequences
-that are recognized.
-.sp
-The options are provided for compatibility with BSD shell scripts:
-\fB\-n\fP suppresses the trailing newline, \fB\-e\fP enables backslash
-interpretation (a no-op, since this is normally done), and \fB\-E\fP which
-suppresses backslash interpretation.
-.\"}}}
-.\"{{{ eval command ...
-.IP "\fBeval\fP \fIcommand ...\fP"
-The arguments are concatenated (with spaces between them) to form
-a single string which the shell then parses and executes
-in the current environment.
-.\"}}}
-.\"{{{ exec [command [arg ...]]
-.IP "\fBexec\fP [\fIcommand\fP [\fIarg\fP ...]]"
-The command is executed without forking, replacing the shell process.
-.sp
-If no arguments are given, any IO redirection is permanent and the shell
-is not replaced.
-Any file descriptors greater than 2 which are opened or \fIdup\fP(2)-ed
-in this way are not made available to other executed commands (\fIi.e.\fP,
-commands that are not built-in to the shell).
-.\"}}}
-.\"{{{ exit [status]
-.IP "\fBexit\fP [\fIstatus\fP]"
-The shell exits with the specified exit status.
-If \fIstatus\fP is not specified, the exit status is the current
-value of the \fB?\fP parameter.
-.\"}}}
-.\"{{{ export [-p] [parameter[=value] ...]
-.IP "\fBexport\fP [\fB\-p\fP] [\fIparameter\fP[\fB=\fP\fIvalue\fP]] ..."
-Sets the export attribute of the named parameters.
-Exported parameters are passed in the environment to executed commands.
-If values are specified, the named parameters also assigned.
-.sp
-If no parameters are specified, the names of all parameters with the export
-attribute are printed one per line, unless the \fB\-p\fP option is used,
-in which case \fBexport\fP commands defining all exported
-parameters, including their values, are printed.
-.\"}}}
-.\"{{{ false
-.IP "\fBfalse\fP"
-A command that exits with a non-zero status.
-.\"}}}
-.\"{{{ fc [-e editor | -l [-n]] [-r] [first [ last ]]
-.IP "\fBfc\fP [\fB\-e\fP \fIeditor\fP | \fB\-l\fP [\fB\-n\fP]] [\fB\-r\fP] [\fIfirst\fP [\fIlast\fP]]"
-\fIfirst\fP and \fIlast\fP select commands from the history.
-Commands can be selected by
-history number, or a string specifying the most recent command starting
-with that string. The \fB\-l\fP option lists the command on stdout,
-and \fB\-n\fP inhibits the default command numbers. The \fB\-r\fP
-option reverses the order of the list. Without \fB\-l\fP, the selected
-commands are edited by the editor specified with the \fB\-e\fP
-option, or if no \fB\-e\fP is specified, the editor specified by the
-\fBFCEDIT\fP parameter (if this parameter is not set, \fB/bin/ed\fP is used),
-and then executed by the shell.
-.\"}}}
-.\"{{{ fc [-e - | -s] [-g] [old=new] [prefix]
-.IP "\fBfc\fP [\fB\-e \-\fP | \fB\-s\fP] [\fB\-g\fP] [\fIold\fP\fB=\fP\fInew\fP] [\fIprefix\fP]"
-Re-execute the selected command (the previous command by default) after
-performing the optional substitution of \fIold\fP with \fInew\fP. If
-\fB\-g\fP is specified, all occurrences of \fIold\fP are replaced with
-\fInew\fP. This command is usually accessed with the predefined alias
-\fBr='fc \-e \-'\fP.
-.\"}}}
-.\"{{{ fg [job ...]
-.IP "\fBfg\fP [\fIjob\fP ...]"
-Resume the specified job(s) in the foreground.
-If no jobs are specified, \fB%+\fP is assumed.
-This command is only available on systems which support job control.
-See Job Control below for more information.
-.\"}}}
-.\"{{{ getopts optstring name [arg ...]
-.IP "\fBgetopts\fP \fIoptstring\fP \fIname\fP [\fIarg\fP ...]"
-\fBgetopts\fP is used by shell procedures to parse the specified arguments
-(or positional parameters, if no arguments are given) and to check for legal
-options.
-\fIoptstring\fP contains the option letters that
-\fBgetopts\fP is to recognize. If a letter is followed by a colon, the
-option is expected to have an argument.
-Arguments containing options must all start with either a \fB\-\fP or
-a \fB+\fP, options that do not take arguments may be grouped in a single
-argument.
-If an option takes an argument and the option character is not the last
-character of the argument it is found in, the remainder of the argument
-is taken to be the option's argument, otherwise, the next argument is
-the option's argument.
-.sp
-Each time \fBgetopts\fP is invoked, it places the next option in
-the shell parameter \fIname\fP and the index of the next argument to be
-processed in the shell parameter \fBOPTIND\fP.
-If the option was introduced with a \fB+\fP, the option placed in
-\fIname\fP is prefixed with a \fB+\fP.
-When an option requires an argument, \fBgetopts\fP places it in the
-shell parameter \fBOPTARG\fP.
-When an illegal option or a missing option argument is
-encountered a question mark or a colon is placed in \fIname\fP
-(indicating an illegal option or missing argument, respectively)
-and \fBOPTARG\fP is set to the option character that caused the problem.
-An error message is also printed to standard error if \fIoptstring\fP
-does not begin with a colon.
-.sp
-When the end of the options is encountered, \fBgetopts\fP exits with a
-non-zero exit status.
-Options end at the first (non-option argument) argument that does not
-start with a \-, or when a \fB\-\-\fP argument is encountered.
-.sp
-Option parsing can be reset by setting \fBOPTIND\fP to 1 (this is done
-automatically whenever the shell or a shell procedure is invoked).
-.sp
-Warning: Changing the value of the shell parameter \fBOPTIND\fP to
-a value other than 1, or parsing different sets of arguments without
-resetting \fBOPTIND\fP may lead to unexpected results.
-.\"}}}
-.\"{{{ hash [-r] [name ...]
-.IP "\fBhash\fP [\fB\-r\fP] [\fIname ...\fP]"
-Without arguments, any hashed executable command pathnames are listed.
-The \fB\-r\fP option causes all hashed commands to be removed
-from the hash table.
-Each \fIname\fP is searched as if it where a command name and added to the
-hash table if it is an executable command.
-.\"}}}
-.\"{{{ jobs [-lpn] [job ...]
-.IP "\fBjobs\fP [\fB\-lpn\fP] [\fIjob\fP ...]"
-Display information about the specified jobs; if no jobs are specified,
-all jobs are displayed.
-The \fB\-n\fP option causes information to be displayed only for jobs
-that have changed state since the last notification.
-If the \fB\-l\fP option is used, the process-id of each process in a job
-is also listed.
-The \fB\-p\fP option causes only the process group of each job to be printed.
-See Job Control below for the format of \fIjob\fP and the displayed job.
-.\"}}}
-.\"{{{ kill [-s signame | -signum | -signame] { job | pid | -pgrp } ...
-.IP "\fBkill\fP [\fB\-s\fP \fIsigname\fP | \fB\-signum\fP | \fB\-signame\fP ] { \fIjob\fP | \fIpid\fP | \fB\-\fP\fIpgrp\fP } ..."
-Send the specified signal to the specified jobs, process ids, or process groups.
-If no signal is specified, the signal TERM is sent.
-If a job is specified, the signal is sent to the job's process group.
-See Job Control below for the format of \fIjob\fP.
-.\"}}}
-.\"{{{ kill -l [exit-status ...]
-.IP "\fBkill \-l\fP [\fIexit-status\fP ...]"
-Print the name of the signal that killed a process which exited with
-the specified \fIexit-status\fPes.
-If no arguments are specified, a list of all the signals, their numbers and
-a short description of them are printed.
-.\"}}}
-.\"{{{ let [expression ...]
-.IP "\fBlet\fP [\fIexpression\fP ...]"
-Each expression is evaluated, see Arithmetic Expressions above.
-If all expressions are successfully evaluated, the exit status
-is 0 (1) if the last expression evaluated to non-zero (zero).
-If an error occurs during the parsing or evaluation of an expression,
-the exit status is greater than 1.
-Since expressions may need to be
-quoted, \fB((\fP \fIexpr\fP \fB))\fP is syntactic sugar for \fBlet
-"\fP\fIexpr\fP\fB"\fP.
-.\"}}}
-.\"{{{ print [-nprsun | -R [-en]] [argument ...]
-.IP "\fBprint\fP [\fB\-nprsu\fP\fIn\fP | \fB\-R\fP [\fB\-en\fP]] [\fIargument ...\fP]"
-\fBPrint\fP prints its arguments on the standard output, separated by
-spaces, and terminated with a newline. The \fB\-n\fP option suppresses
-the newline. By default, certain C escapes are translated. These
-include \eb, \ef, \en, \er, \et, \ev, and \e0### (# is an octal digit, of
-which there may be 0 to 3).
-\ec is equivalent to using the \fB\-n\fP option. \e expansion may be
-inhibited with the \fB\-r\fP option.
-The \fB\-s\fP option prints to the history file instead of standard output,
-the \fB\-u\fP option prints to file descriptor \fIn\fP (\fIn\fP
-defaults to 1 if omitted), and the \fB\-p\fP option prints to the co-process
-(see Co-Processes above).
-.sp
-The \fB\-R\fP option is used to emulate, to some degree, the BSD echo
-command, which does not process \e sequences unless the \fB\-e\fP option
-is given.
-As above, the \fB\-n\fP option suppresses the trailing newline.
-.\"}}}
-.\"{{{ pwd [-LP]
-.IP "\fBpwd\fP [\fB\-LP\fP]"
-Print the present working directory.
-If \fB\-L\fP option is used or if the \fBphysical\fP option
-(see \fBset\fP command below) isn't set, the logical path is printed
-(\fIi.e.\fP, the path used to \fBcd\fP to the current directory).
-If \fB\-P\fP option (physical path) is used or if the \fBphysical\fP option
-is set, the path determined from the filesystem (by following \fB..\fP
-directories to the root directory) is printed.
-.\"}}}
-.\"{{{ read [-prsun] [parameter ...]
-.IP "\fBread\fP [\fB\-prsu\fP\fIn\fP] [\fIparameter ...\fP]"
-Reads a line of input from standard input, separate the line into fields using
-the \fBIFS\fP parameter (see Substitution above), and assign each field to the
-specified parameters.
-If there are more parameters than fields, the extra parameters are set to null,
-or alternatively, if there are more fields than parameters, the last parameter
-is assigned the remaining fields (inclusive of any separating spaces).
-If no parameters are specified, the \fBREPLY\fP parameter is used.
-If the input line ends in a backslash and the \fB\-r\fP option was not used, the
-backslash and newline are stripped and more input is read.
-If no input is read, \fBread\fP exits with a non-zero status.
-.sp
-The first parameter may have a question mark and a string appended to it, in
-which case the string is used as a prompt (printed to standard error before
-any input is read) if the input is a tty
-(\fIe.g.\fP, \fBread nfoo?'number of foos: '\fP).
-.sp
-The \fB\-u\fP\fIn\fP and \fB\-p\fP options cause input to be read
-from file descriptor \fIn\fP or the current co-process (see Co-Processes above
-for comments on this), respectively.
-If the \fB\-s\fP option is used, input is saved to the history file.
-.\"}}}
-.\"{{{ readonly [-p] [parameter[=value] ...]
-.IP "\fBreadonly\fP [\fB\-p\fP] [\fIparameter\fP[\fB=\fP\fIvalue\fP]] ..."
-Sets the readonly attribute of the named parameters. If values are given,
-parameters are set to them before setting the attribute.
-Once a parameter is made readonly, it cannot be unset and its value cannot
-be changed.
-.sp
-If no parameters are specified, the names of all parameters with the readonly
-attribute are printed one per line, unless the \fB\-p\fP option is used,
-in which case \fBreadonly\fP commands defining all readonly
-parameters, including their values, are printed.
-.\"}}}
-.\"{{{ return [status]
-.IP "\fBreturn\fP [\fIstatus\fP]"
-Returns from a function or \fB.\fP script, with exit status \fIstatus\fP.
-If no \fIstatus\fP is given, the exit status of the last executed command
-is used.
-If used outside of a function or \fB.\fP script, it has the same effect
-as \fBexit\fP.
-Note that pdksh treats both profile and \fB$ENV\fP files as \fB.\fP scripts,
-while the original Korn shell only treats profiles as \fB.\fP scripts.
-.\"}}}
-.\"{{{ set [+-abCefhkmnpsuvxX] [+-o [option]] [+-A name] [--] [arg ...]
-.IP "\fBset\fP [\fB\(+-abCefhkmnpsuvxX\fP] [\fB\(+-o\fP [\fIoption\fP]] [\fB\(+-A\fP \fIname\fP] [\fB\-\-\fP] [\fIarg\fP ...]"
-The set command can be used to set (\fB\-\fP) or clear (\fB+\fP) shell options,
-set the positional parameters, or set an array parameter.
-Options can be changed using the \fB\(+-o\fP \fIoption\fP syntax,
-where \fIoption\fP is the long name of an option, or using
-the \fB\(+-\fP\fIletter\fP syntax, where \fIletter\fP is the
-option's single letter name (not all options have a single letter name).
-The following table lists both option letters (if they exist) and long names
-along with a description of what the option does.
-.sp
-.TS
-expand;
-afB lfB lw(3i).
-\-A T{
-Sets the elements of the array parameter \fIname\fP to \fIarg\fP ...;
-If \fB\-A\fP is used, the array is reset (\fIi.e.\fP, emptied) first;
-if \fB+A\fP is used, the first N elements are set (where N is the number
-of \fIarg\fPs), the rest are left untouched.
-T}
-\-a allexport T{
-all new parameters are created with the export attribute
-T}
-\-b notify T{
-Print job notification messages asynchronously, instead of just before the
-prompt.
-Only used if job control is enabled (\fB\-m\fP).
-T}
-\-C noclobber T{
-Prevent \fB>\fP redirection from overwriting existing files (\fB>|\fP must
-be used to force an overwrite).
-T}
-\-e errexit T{
-Exit (after executing the \fBERR\fP trap) as soon as an error occurs or
-a command fails (\fIi.e.\fP, exits with a non-zero status).
-This does not apply to commands whose exit status is explicitly tested by a
-shell construct such as \fBif\fP, \fBuntil\fP, \fBwhile\fP, \fB&&\fP or
-\fB||\fP statements.
-T}
-\-f noglob T{
-Do not expand file name patterns.
-T}
-\-h trackall T{
-Create tracked aliases for all executed commands (see Aliases above).
-On by default for non-interactive shells.
-T}
-\-i interactive T{
-Enable interactive mode \- this can only be set/unset when the shell is
-invoked.
-T}
-\-k keyword T{
-Parameter assignments are recognized anywhere in a command.
-T}
-\-l login T{
-The shell is a login shell \- this can only be set/unset when the shell is
-invoked (see Shell Startup above).
-T}
-\-m monitor T{
-Enable job control (default for interactive shells).
-T}
-\-n noexec T{
-Do not execute any commands \- useful for checking the syntax of scripts
-(ignored if interactive).
-T}
-\-p privileged T{
-Set automatically if, when the shell starts, the read uid or gid does not
-match the effective uid or gid, respectively.
-See Shell Startup above for a description of what this
-means.
-T}
--r restricted T{
-Enable restricted mode \(em this option can only be used when the shell is
-invoked. See Shell Startup above for a description of what this
-means.
-T}
-\-s stdin T{
-If used when the shell is invoked, commands are read from standard input.
-Set automatically if the shell is invoked with no arguments.
-.sp
-When \fB\-s\fP is used in the \fBset\fP command, it causes the specified
-arguments to be sorted before assigning them to the positional parameters
-(or to array \fIname\fP, if \fB\-A\fP is used).
-T}
-\-u nounset T{
-Referencing of an unset parameter is treated as an error, unless
-one of the \fB\-\fP, \fB+\fP or \fB=\fP modifiers is used.
-T}
-\-v verbose T{
-Write shell input to standard error as it is read.
-T}
-\-x xtrace T{
-Print commands and parameter assignments when they are executed,
-preceded by the value of \fBPS4\fP.
-T}
-\-X markdirs T{
-Mark directories with a trailing \fB/\fP during file name generation.
-T}
- bgnice T{
-Background jobs are run with lower priority.
-T}
- braceexpand T{
-Enable brace expansion (aka, alternation).
-T}
- emacs T{
-Enable BRL emacs-like command line editing (interactive shells only);
-see Emacs Interactive Input Line Editing.
-T}
- gmacs T{
-Enable gmacs-like (Gosling emacs) command line editing (interactive shells
-only);
-currently identical to emacs editing except that transpose (^T) acts
-slightly differently.
-T}
- ignoreeof T{
-The shell will not exit on when end-of-file is read, \fBexit\fP must be used.
-T}
- nohup T{
-Do not kill running jobs with a \fBHUP\fP signal when a login shell exists.
-Currently set by default, but this will change in the future to be compatible
-with the original Korn shell (which doesn't have this option, but does
-send the \fBHUP\fP signal).
-T}
- nolog T{
-No effect \- in the original Korn shell, this prevents function definitions
-from being stored in the history file.
-T}
- physical T{
-Causes the \fBcd\fP and \fBpwd\fP commands to use `physical'
-(\fIi.e.\fP, the filesystem's) \fB..\fP directories instead of `logical'
-directories (\fIi.e.\fP, the shell handles \fB..\fP, which allows the user
-to be obliveous of symlink links to directories).
-Clear by default. Note that setting
-this option does not effect the current value of the \fBPWD\fP parameter;
-only the \fBcd\fP command changes \fBPWD\fP.
-See the \fBcd\fP and \fBpwd\fP commands above for more details.
-T}
- posix T{
-Enable posix mode. See POSIX Mode above.
-T}
- vi T{
-Enable vi-like command line editing (interactive shells only).
-T}
- viraw T{
-No effect \- in the original Korn shell, unless viraw was set, the vi command
-line mode would let the tty driver do the work until ESC (^[) was entered.
-pdksh is always in viraw mode.
-T}
- vi-esccomplete T{
-In vi command line editing, do command / file name completion when
-escape (^[) is entered in command mode.
-T}
- vi-show8 T{
-Prefix characters with the eighth bit set with `M-'.
-If this option is not set, characters in the range
-128-160 are printed as is, which may cause problems.
-T}
- vi-tabcomplete T{
-In vi command line editing, do command / file name completion when
-tab (^I) is entered in insert mode.
-T}
-.TE
-.sp
-These options can also be used upon invocation of the shell. The current
-set of options (with single letter names) can be found in the
-parameter \fB\-\fP.
-\fBset -o\fP with no option name will list all the options and whether each
-is on or off; \fBset +o\fP will print the long names of all options that
-are currently on.
-.sp
-Remaining arguments, if any, are positional parameters and are assigned,
-in order, to the
-positional parameters (\fIi.e.\fP, \fB1\fP, \fB2\fP, \fIetc.\fP).
-If options are ended with \fB\-\-\fP and there are no remaining arguments,
-all positional parameters are cleared.
-If no options or arguments are given, then the values of all names are printed.
-For unknown historical reasons, a lone \fB\-\fP option is treated specially:
-it clears both the \fB\-x\fP and \fB\-v\fP options.
-.\"}}}
-.\"{{{ shift [number]
-.IP "\fBshift\fP [\fInumber\fP]"
-The positional parameters \fInumber\fP+1, \fInumber\fP+2 \fIetc.\fP\& are
-renamed to \fB1\fP, \fB2\fP, \fIetc.\fP
-\fInumber\fP defaults to 1.
-.\"}}}
-.\"{{{ test expression, [ expression ]
-.IP "\fBtest\fP \fIexpression\fP"
-.IP "\fB[\fP \fIexpression\fP \fB]\fP"
-\fBtest\fP evaluates the \fIexpression\fP and returns zero status if
-true, and 1 status if false and greater than 1 if there was an error.
-It is normally used as the
-condition command of \fBif\fP and \fBwhile\fP statements.
-The following basic expressions are available:
-.sp
-.TS
-afB ltw(2.8i).
-\fIstr\fP T{
-\fIstr\fP has non-zero length. Note that there is the potential
-for problems if \fIstr\fP turns out to be an operator (\fIe.g.\fP, \fB-r\fP)
-- it is generally better to use a test like
-.RS
-\fB[ X"\fP\fIstr\fP\fB" != X ]\fP
-.RE
-instead (double quotes are used in case \fIstr\fP contains spaces or file
-globing characters).
-T}
-\-r \fIfile\fP T{
-\fIfile\fP exists and is readable
-T}
-\-w \fIfile\fP T{
-\fIfile\fP exists and is writable
-T}
-\-x \fIfile\fP T{
-\fIfile\fP exists and is executable
-T}
-\-a \fIfile\fP T{
-\fIfile\fP exists
-T}
-\-e \fIfile\fP T{
-\fIfile\fP exists
-T}
-\-f \fIfile\fP T{
-\fIfile\fP is a regular file
-T}
-\-d \fIfile\fP T{
-\fIfile\fP is a directory
-T}
-\-c \fIfile\fP T{
-\fIfile\fP is a character special device
-T}
-\-b \fIfile\fP T{
-\fIfile\fP is a block special device
-T}
-\-p \fIfile\fP T{
-\fIfile\fP is a named pipe
-T}
-\-u \fIfile\fP T{
-\fIfile\fP's mode has setuid bit set
-T}
-\-g \fIfile\fP T{
-\fIfile\fP's mode has setgid bit set
-T}
-\-k \fIfile\fP T{
-\fIfile\fP's mode has sticky bit set
-T}
-\-s \fIfile\fP T{
-\fIfile\fP is not empty
-T}
-\-O \fIfile\fP T{
-\fIfile\fP's owner is the shell's effective user-ID
-T}
-\-G \fIfile\fP T{
-\fIfile\fP's group is the shell's effective group-ID
-T}
-\-h \fIfile\fP T{
-\fIfile\fP is a symbolic link
-T}
-\-H \fIfile\fP T{
-\fIfile\fP is a context dependent directory (only useful on HP-UX)
-T}
-\-L \fIfile\fP T{
-\fIfile\fP is a symbolic link
-T}
-\-S \fIfile\fP T{
-\fIfile\fP is a socket
-T}
-\-o \fIoption\fP T{
-shell \fIoption\fP is set (see \fBset\fP command above for list of options).
-As a non-standard extension, if the option starts with a \fB!\fP, the test
-is negated; the test always fails if option doesn't exist (thus
-.RS
-\fB[ -o \fP\fIfoo\fP \fB-o -o !\fP\fIfoo\fP \fB]\fP
-.RE
-returns true if and only if option \fIfoo\fP exists).
-T}
-\fIfile\fP \-nt \fIfile\fP T{
-first \fIfile\fP is newer than second \fIfile\fP
-T}
-\fIfile\fP \-ot \fIfile\fP T{
-first \fIfile\fP is older than second \fIfile\fP
-T}
-\fIfile\fP \-ef \fIfile\fP T{
-first \fIfile\fP is the same file as second \fIfile\fP
-T}
-\-t [\fIfd\fP] T{
-file descriptor is a tty device.
-Default value of \fIfd\fP is 1.
-T}
-\fIstring\fP T{
-\fIstring\fP is not empty
-T}
-\-z \fIstring\fP T{
-\fIstring\fP is empty
-T}
-\-n \fIstring\fP T{
-\fIstring\fP is not empty
-T}
-\fIstring\fP = \fIstring\fP T{
-strings are equal
-T}
-\fIstring\fP == \fIstring\fP T{
-strings are equal
-T}
-\fIstring\fP != \fIstring\fP T{
-strings are not equal
-T}
-\fInumber\fP \-eq \fInumber\fP T{
-numbers compare equal
-T}
-\fInumber\fP \-ne \fInumber\fP T{
-numbers compare not equal
-T}
-\fInumber\fP \-ge \fInumber\fP T{
-numbers compare greater than or equal
-T}
-\fInumber\fP \-gt \fInumber\fP T{
-numbers compare greater than
-T}
-\fInumber\fP \-le \fInumber\fP T{
-numbers compare less than or equal
-T}
-\fInumber\fP \-lt \fInumber\fP T{
-numbers compare less than
-T}
-.TE
-.sp
-The above basic expressions, in which unary operators have precedence over
-binary operators, may be combined with the following operators
-(listed in increasing order of precedence):
-.sp
-.TS
-afB l.
-\fIexpr\fP \-o \fIexpr\fP logical or
-\fIexpr\fP \-a \fIexpr\fP logical and
-! \fIexpr\fP logical not
-( \fIexpr\fP ) grouping
-.TE
-.sp
-On operating systems not supporting \fB/dev/fd/\fP\fIn\fP devices
-(where \fIn\fP is a file descriptor number),
-the \fBtest\fP command will attempt to fake it for all tests that
-operate on files (except the \fB-e\fP test).
-I.e., \fB[ -w /dev/fd/2 ]\fP tests if file descriptor 2 is writable.
-.sp
-Note that some special rules are applied (courtesy of POSIX) if the
-number of arguments to \fBtest\fP or \fB[\fP \&... \fB]\fP is less than
-five: if leading \fB!\fP arguments can be stripped such that only one
-argument remains then a string length test is performed (again, even if
-the argument is a unary operator);
-if leading \fB!\fP arguments can be stripped such that three
-arguments remain and the second argument is a binary operator, then the
-binary operation is performed (even if first argument is a unary
-operator, including an unstripped \fB!\fP).
-.sp
-\fBNote:\fP A common mistake is to use \fBif [ $foo = bar ]\fP which
-fails if parameter \fBfoo\fP is null or unset, if it has embedded spaces
-(\fIi.e.\fP, \fBIFS\fP characters), or if it is a unary operator like \fB!\fP or
-\fB\-n\fP. Use tests like \fBif [ "X$foo" = Xbar ]\fP instead.
-.\"}}}
-.\"{{{ times
-.IP \fBtimes\fP
-Print the accumulated user and system times used by the shell and by
-processes which have exited that the shell started.
-.\"}}}
-.\"{{{ trap [handler signal ...]
-.IP "\fBtrap\fP [\fIhandler\fP \fIsignal ...\fP]"
-Sets trap handler that is to be executed when any of the specified signals
-are received.
-\fBHandler\fP is either a null string, indicating the signals are to
-be ignored, a minus (\fB\-\fP), indicating that the default action is to
-be taken for the signals (see signal(2 or 3)), or a string containing shell
-commands to be evaluated and executed at the first opportunity (\fIi.e.\fP,
-when the current command completes, or before printing the next \fBPS1\fP
-prompt) after receipt of one of the signals.
-\fBSignal\fP is the name of a signal (\fIe.g.\fP, PIPE or ALRM) or the number
-of the signal (see \fBkill \-l\fP command above).
-There are two special signals: \fBEXIT\fP (also known as \fB0\fP), which
-is executed when the shell is about to exit, and \fBERR\fP which is
-executed after an error occurs (an error is something that would cause
-the shell to exit if the \fB\-e\fP or \fBerrexit\fP option were set \(em
-see \fBset\fP command above).
-\fBEXIT\fP handlers are executed in the environment of the last executed
-command.
-Note that for non-interactive shells, the trap handler cannot be changed for
-signals that were ignored when the shell started.
-.sp
-With no arguments, \fBtrap\fP lists, as a series of \fBtrap\fP commands,
-the current state of the traps that have been set since the shell started.
-.sp
-.\" todo: add these features (trap DEBUG, trap ERR/EXIT in function)
-The original Korn shell's \fBDEBUG\fP trap and the handling of \fBERR\fP and
-\fBEXIT\fP traps in functions are not yet implemented.
-.\"}}}
-.\"{{{ true
-.IP \fBtrue\fP
-A command that exits with a zero value.
-.\"}}}
-.\"{{{ typeset [[+-Ulrtux] [-L[n]] [-R[n]] [-Z[n]] [-i[n]] | -f [-tux]] [name[=value] ...]
-.IP "\fBtypeset\fP [[\(+-Ulrtux] [\fB\-L\fP[\fIn\fP]] [\fB\-R\fP[\fIn\fP]] [\fB\-Z\fP[\fIn\fP]] [\fB\-i\fP[\fIn\fP]] | \fB\-f\fP [\fB\-tux\fP]] [\fIname\fP[\fB=\fP\fIvalue\fP] ...]"
-Display or set parameter attributes.
-With no \fIname\fP arguments, parameter attributes are displayed: if no options
-arg used, the current attributes of all parameters are printed as typeset
-commands; if an option is given (or \fB\-\fP with no option letter)
-all parameters and their values with the specified attributes are printed;
-if options are introduced with \fB+\fP, parameter values are not printed.
-.sp
-If \fIname\fP arguments are given, the attributes of the named parameters
-are set (\fB\-\fP) or cleared (\fB+\fP).
-Values for parameters may optionally be specified.
-If typeset is used inside a function, any newly created parameters are local
-to the function.
-.sp
-When \fB\-f\fP is used, typeset operates on the attributes of functions.
-As with parameters, if no \fIname\fPs are given, functions are listed
-with their values (\fIi.e.\fP, definitions) unless options are introduced with
-\fB+\fP, in which case only the function names are reported.
-.sp
-.TS
-expand;
-afB lw(4.5i).
-\-L\fIn\fP T{
-Left justify attribute: \fIn\fP specifies the field width.
-If \fIn\fP is not specified, the current width of a parameter (or the
-width of its first assigned value) is used.
-Leading white space (and zeros, if used with the \fB\-Z\fP option) is stripped.
-If necessary, values are either truncated or space padded to fit the
-field width.
-T}
-\-R\fIn\fP T{
-Right justify attribute: \fIn\fP specifies the field width.
-If \fIn\fP is not specified, the current width of a parameter (or the
-width of its first assigned value) is used.
-Trailing white space are stripped.
-If necessary, values are either stripped of leading characters
-or space padded to make them fit the field width.
-T}
-\-Z\fIn\fP T{
-Zero fill attribute: if not combined with \fB\-L\fP, this is the
-same as \fB\-R\fP, except zero padding is used instead of space padding.
-T}
-\-i\fIn\fP T{
-integer attribute:
-\fIn\fP specifies the base to use when displaying the integer
-(if not specified, the base given in the first assignment is used).
-Parameters with this attribute may be assigned values containing
-arithmetic expressions.
-T}
-\-U T{
-unsigned integer attribute: integers are printed as unsigned values
-(only useful when combined with the \fB\-i\fP option).
-This option is not in the original Korn shell.
-T}
-\-f T{
-Function mode: display or set functions and their attributes, instead of
-parameters.
-T}
-\-l T{
-Lower case attribute: all upper case characters in values are converted to
-lower case.
-(In the original Korn shell, this parameter meant `long integer' when used
-with the \fB\-i\fP option).
-T}
-\-r T{
-Readonly attribute: parameters with the this attribute may not be assigned to
-or unset.
-Once this attribute is set, it can not be turned off.
-T}
-\-t T{
-Tag attribute: has no meaning to the shell; provided for application use.
-.sp
-For functions, \fB\-t\fP is the trace attribute.
-When functions with the trace attribute are executed, the \fBxtrace\fP (\fB\-x\fP) shell option is temporarily turned on.
-T}
-\-u T{
-Upper case attribute: all lower case characters in values are converted to
-upper case.
-(In the original Korn shell, this parameter meant `unsigned integer' when used
-with the \fB\-i\fP option, which meant upper case letters would never be used
-for bases greater than 10. See the \fB\-U\fP option).
-.sp
-For functions, \fB\-u\fP is the undefined attribute. See Functions above
-for the implications of this.
-T}
-\-x T{
-Export attribute: parameters (or functions) are placed in the environment of
-any executed commands. Exported functions are not implemented yet.
-T}
-.TE
-.\"}}}
-.\"{{{ ulimit [-acdfHlmnpsStvw] [value]
-.IP "\fBulimit\fP [\fB\-acdfHlmnpsStvw\fP] [\fIvalue\fP]"
-Display or set process limits.
-If no options are used, the file size limit (\fB\-f\fP) is assumed.
-\fBvalue\fP, if specified, may be either be an arithmetic expression or the
-word \fBunlimited\fP.
-The limits affect the shell and any processes created by the shell after
-a limit is imposed.
-Note that some systems may not allow limits to be increased once they
-are set.
-Also note that the types of limits available are system dependent \- some
-systems have only the \fB\-f\fP limit.
-.RS
-.IP \fB\-a\fP
-Displays all limits; unless \fB\-H\fP is used, soft limits are displayed.
-.IP \fB\-H\fP
-Set the hard limit only (default is to set both hard and soft limits).
-.IP \fB\-S\fP
-Set the soft limit only (default is to set both hard and soft limits).
-.IP \fB\-c\fP
-Impose a size limit of \fIn\fP blocks on the size of core dumps.
-.IP \fB\-d\fP
-Impose a size limit of \fIn\fP kbytes on the size of the data area.
-.IP \fB\-f\fP
-Impose a size limit of \fIn\fP blocks on files written by the shell and
-its child processes (files of any size may be read).
-.IP \fB\-l\fP
-Impose a limit of \fIn\fP kbytes on the amount of locked (wired) physical
-memory.
-.IP \fB\-m\fP
-Impose a limit of \fIn\fP kbytes on the amount of physical memory used.
-.IP \fB\-n\fP
-Impose a limit of \fIn\fP file descriptors that can be open at once.
-.IP \fB\-p\fP
-Impose a limit of \fIn\fP processes that can be run by the user at any one
-time.
-.IP \fB\-s\fP
-Impose a size limit of \fIn\fP kbytes on the size of the stack area.
-.IP \fB\-t\fP
-Impose a time limit of \fIn\fP cpu seconds to be used by each process.
-.IP \fB\-v\fP
-Impose a limit of \fIn\fP kbytes on the amount of virtual memory used;
-on some systems this is the maximum allowable virtual address (in bytes,
-not kbytes).
-.IP \fB\-w\fP
-Impose a limit of \fIn\fP kbytes on the amount of swap space used.
-.PP
-As far as \fBulimit\fP is concerned, a block is 512 bytes.
-.RE
-.\"}}}
-.\"{{{ umask [-S] [mask]
-.IP "\fBumask\fP [\fB\-S\fP] [\fImask\fP]"
-.RS
-Display or set the file permission creation mask, or umask (see \fIumask\fP(2)).
-If the \fB\-S\fP option is used, the mask displayed or set is symbolic,
-otherwise it is an octal number.
-.sp
-Symbolic masks are like those used by \fIchmod\fP(1):
-.RS
-[\fBugoa\fP]{{\fB=+-\fP}{\fBrwx\fP}*}+[\fB,\fP...]
-.RE
-in which the first group of characters is the \fIwho\fP part, the second
-group is the \fIop\fP part, and the last group is the \fIperm\fP part.
-The \fIwho\fP part specifies which part of the umask is to be modified.
-The letters mean:
-.RS
-.IP \fBu\fP
-the user permissions
-.IP \fBg\fP
-the group permissions
-.IP \fBo\fP
-the other permissions (non-user, non-group)
-.IP \fBa\fP
-all permissions (user, group and other)
-.RE
-.sp
-The \fIop\fP part indicates how the \fIwho\fP permissions are to be modified:
-.RS
-.IP \fB=\fP
-set
-.IP \fB+\fP
-added to
-.IP \fB\-\fP
-removed from
-.RE
-.sp
-The \fIperm\fP part specifies which permissions are to be set, added or removed:
-.RS
-.IP \fBr\fP
-read permission
-.IP \fBw\fP
-write permission
-.IP \fBx\fP
-execute permission
-.RE
-.sp
-When symbolic masks are used, they describe what permissions may
-be made available (as opposed to octal masks in which a set bit means
-the corresponding bit is to be cleared).
-Example: `ug=rwx,o=' sets the mask so files will not be readable, writable
-or executable by `others', and is equivalent (on most systems) to the octal
-mask `07'.
-.RE
-.\"}}}
-.\"{{{ unalias [-adt] name ...
-.IP "\fBunalias\fP [\fB\-adt\fP] [\fIname1\fP ...]"
-The aliases for the given names are removed.
-If the \fB\-a\fP option is used, all aliases are removed.
-If the \fB\-t\fP or \fB\-d\fP options are used, the indicated operations
-are carried out on tracked or directory aliases, respectively.
-.\"}}}
-.\"{{{ unset [-fv] parameter ...
-.IP "\fBunset\fP [\fB\-fv\fP] \fIparameter\fP ..."
-Unset the named parameters (\fB\-v\fP, the default) or functions (\fB\-f\fP).
-The exit status is non-zero if any of the parameters were already unset,
-zero otherwise.
-.\"}}}
-.\"{{{ wait [job]
-.IP "\fBwait\fP [\fIjob\fP]"
-Wait for the specified job(s) to finish.
-The exit status of wait is that of the last specified job:
-if the last job is killed by a signal, the exit status is 128 + the
-number of the signal (see \fBkill \-l\fP \fIexit-status\fP above); if the last
-specified job can't be found (because it never existed, or had already
-finished), the exit status of wait is 127.
-See Job Control below for the format of \fIjob\fP.
-\fBWait\fP will return if a signal for which a trap has been set is received,
-or if a HUP, INT or QUIT signal is received.
-.sp
-If no jobs are specified, \fBwait\fP waits for all currently running jobs
-(if any) to finish and exits with a zero status.
-If job monitoring is enabled, the completion status of jobs is
-printed (this is not the case when jobs are explicitly specified).
-.\"}}}
-.\"{{{ whence [-pv] [name ...]
-.IP "\fBwhence\fP [\fB\-pv\fP] [name ...]"
-For each name, the type of command is listed (reserved word, built-in, alias,
-function, tracked alias or executable).
-If the \fB\-p\fP option is used, a path search done even if \fIname\fP
-is a reserved word, alias, \fIetc.\fP
-Without the \fB\-v\fP option, \fBwhence\fP is similar to \fBcommand \-v\fP
-except that \fBwhence\fP will find reserved words and won't print aliases
-as alias commands;
-with the \fB\-v\fP option, \fBwhence\fP is the same as \fBcommand \-V\fP.
-Note that for \fBwhence\fP, the \fB\-p\fP option does not affect the search
-path used, as it does for \fBcommand\fP.
-If the type of one or more of the names could not be determined, the
-exit status is non-zero.
-.\"}}}
-.\"}}}
-.\"{{{ job control (and its built-in commands)
-.SS "Job Control"
-Job control refers to the shell's ability to monitor and control \fBjobs\fP,
-which are processes or groups of processes created for commands or pipelines.
-At a minimum, the shell keeps track of the status of the background
-(\fIi.e.\fP, asynchronous) jobs that currently exist; this information can be
-displayed using the \fBjobs\fP command.
-If job control is fully enabled (using \fBset \-m\fP or
-\fBset \-o monitor\fP), as it is for interactive shells,
-the processes of a job are placed in their own process group,
-foreground jobs can be stopped by typing the suspend character from the
-terminal (normally ^Z),
-jobs can be restarted in either the foreground
-or background, using the \fBfg\fP and \fBbg\fP commands, respectively,
-and the state of the terminal is saved or restored when a foreground
-job is stopped or restarted, respectively.
-.sp
-Note that only commands that create processes (\fIe.g.\fP,
-asynchronous commands, subshell commands, and non-built-in,
-non-function commands) can be stopped; commands like \fBread\fP cannot be.
-.sp
-When a job is created, it is assigned a job-number.
-For interactive shells, this number is printed inside \fB[\fP..\fB]\fP,
-followed by the process-ids of the processes in the job when an asynchronous
-command is run.
-A job may be referred to in \fBbg\fP, \fBfg\fP, \fBjobs\fP, \fBkill\fP and
-\fBwait\fP commands either by the process id of the last process in the
-command pipeline (as stored in the \fB$!\fP parameter) or by prefixing the
-job-number with a percent sign (\fB%\fP).
-Other percent sequences can also be used to refer to jobs:
-.sp
-.TS
-expand;
-afB lw(4.5i).
-%+ T{
-The most recently stopped job, or, if there are no stopped jobs, the oldest
-running job.
-T}
-%%\fR, \fP% T{
-Same as \fB%+\fP.
-T}
-%\- T{
-The job that would be the \fB%+\fP job, if the later did not exist.
-T}
-%\fIn\fP T{
-The job with job-number \fIn\fP.
-T}
-%?\fIstring\fP T{
-The job containing the string \fIstring\fP (an error occurs if multiple jobs
-are matched).
-T}
-%\fIstring\fP T{
-The job starting with string \fIstring\fP (an error occurs if multiple jobs
-are matched).
-T}
-.TE
-.sp
-When a job changes state (\fIe.g.\fP, a background job finishes or foreground
-job is stopped), the shell prints the following status information:
-.RS
-\fB[\fP\fInumber\fP\fB]\fP \fIflag status command\fP
-.RE
-where
-.IP "\ \fInumber\fP"
-is the job-number of the job.
-.IP "\ \fIflag\fP"
-is \fB+\fP or \fB-\fP if the job is the \fB%+\fP or \fB%-\fP job,
-respectively, or space if it is neither.
-.IP "\ \fIstatus\fP"
-indicates the current state of the job and can be
-.RS
-.IP "\fBRunning\fP"
-the job has neither stopped or exited (note that running does not
-necessarily mean consuming CPU time \(em the process could be blocked waiting
-for some event).
-.IP "\fBDone\fP [\fB(\fP\fInumber\fP\fB)\fP]"
-the job exited. \fInumber\fP is the exit status of the job, which is
-omitted if the status is zero.
-.IP "\fBStopped\fP [\fB(\fP\fIsignal\fP\fB)\fP]"
-the job was stopped by the indicated \fIsignal\fP (if no signal is given,
-the job was stopped by SIGTSTP).
-.IP "\fIsignal-description\fP [\fB(core dumped)\fP]"
-the job was killed by a signal (\fIe.g.\fP, Memory\ fault,
-Hangup, \fIetc.\fP \(em use
-\fBkill \-l\fP for a list of signal descriptions).
-The \fB(core\ dumped)\fP message indicates the process created a core file.
-.RE
-.IP "\ \fIcommand\fP"
-is the command that created the process.
-If there are multiple processes in the job, then each process will
-have a line showing its \fIcommand\fP and possibly its \fIstatus\fP,
-if it is different from the status of the previous process.
-.PP
-When an attempt is made to exit the shell while there are jobs in
-the stopped state, the shell warns the user that there are stopped jobs
-and does not exit.
-If another attempt is immediately made to exit the shell, the stopped
-jobs are sent a \fBHUP\fP signal and the shell exits.
-Similarly, if the \fBnohup\fP option is not set and there are running
-jobs when an attempt is made to exit a login shell, the shell warns the
-user and does not exit.
-If another attempt is immediately made to exit the shell, the running
-jobs are sent a \fBHUP\fP signal and the shell exits.
-.\"}}}
-.\"{{{ Emacs Interactive Input Line Editing
-.SS "Emacs Interactive Input Line Editing"
-When the \fBemacs\fP option is set, interactive input line editing is
-enabled. \fBWarning\fP: This mode is slightly different from the emacs
-mode in the original Korn shell and the 8th bit is stripped in emacs mode.
-In this mode various editing commands (typically bound to one or more
-control characters) cause immediate actions without waiting for a
-new-line. Several editing commands are bound to particular control
-characters when the shell is invoked; these bindings can be changed
-using the following commands:
-.\"{{{ bind
-.IP \fBbind\fP
-The current bindings are listed.
-.\"}}}
-.\"{{{ bind string=[editing-command]
-.IP "\fBbind\fP \fIstring\fP\fB=\fP[\fIediting-command\fP]"
-The specified editing command is bound to the given \fBstring\fP, which
-should consist of a control character (which may be written using caret
-notation \fB^\fP\fIX\fP), optionally preceded by one of the two prefix
-characters. Future input of the \fIstring\fP will cause the editing
-command to be immediately invoked. Note that although only two prefix
-characters (usually ESC and ^X) are supported, some multi-character
-sequences can be supported. The following binds the arrow keys on
-an ANSI terminal, or xterm (these are in the default bindings). Of course
-some escape sequences won't work out quite this nicely:
-.sp
-.RS
-\fBbind '^[['=prefix\-2
-.br
-bind '^XA'=up\-history
-.br
-bind '^XB'=down\-history
-.br
-bind '^XC'=forward\-char
-.br
-bind '^XD'=backward\-char\fP
-.RE
-.\"}}}
-.\"{{{ bind -l
-.IP "\fBbind \-l\fP"
-Lists the names of the functions to which keys may be bound.
-.\"}}}
-.\"{{{ bind -m string=[substitute]
-.IP "\fBbind \-m\fP \fIstring\fP\fB=\fP[\fIsubstitute\fP]"
-The specified input \fIstring\fP will afterwards be immediately
-replaced by the given \fIsubstitute\fP string, which may contain
-editing commands.
-.\"}}}
-.PP
-The following is a list of editing commands available.
-Each description starts with the name of the command,
-a \fIn\fP, if the command can be prefixed with a count,
-and any keys the command is bound to by default (written using
-caret notation, \fIe.g.\fP, ASCII ESC character is written as ^[).
-A count prefix for a command is entered using the sequence
-\fB^[\fP\fIn\fP, where \fIn\fP is a sequence of 1 or more digits;
-unless otherwise specified, if a count is omitted, it defaults to 1.
-Note that editing command names are
-used only with the \fBbind\fP command. Furthermore, many editing
-commands are useful only on terminals with a visible cursor. The
-default bindings were chosen to resemble corresponding EMACS key
-bindings. The users tty characters (\fIe.g.\fP, ERASE) are bound to
-reasonable substitutes and override the default bindings.
-.\"{{{ abort ^G
-.IP "\fBabort ^G\fP"
-Useful as a response to a request for a \fBsearch-history\fP pattern in
-order to abort the search.
-.\"}}}
-.\"{{{ auto-insert n
-.IP "\fBauto-insert\fP \fIn\fP"
-Simply causes the character to appear as literal input. Most ordinary
-characters are bound to this.
-.\"}}}
-.\"{{{ backward-char n ^B
-.IP "\fBbackward-char\fP \fIn\fP \fB^B\fP"
-Moves the cursor backward \fIn\fP characters.
-.\"}}}
-.\"{{{ backward-word n ^[B
-.IP "\fBbackward-word\fP \fIn\fP \fB^[B\fP"
-Moves the cursor backward to the beginning of a word; words consist
-of alphanumerics, underscore (_) and dollar ($).
-.\"}}}
-.\"{{{ beginning-of-history ^[<
-.IP "\fBbeginning-of-history ^[<\fP"
-Moves to the beginning of the history.
-.\"}}}
-.\"{{{ beginning-of-line ^A
-.IP "\fBbeginning-of-line ^A\fP"
-Moves the cursor to the beginning of the edited input line.
-.\"}}}
-.\"{{{ capitalize-word n ^[c, ^[C
-.IP "\fBcapitalize-word\fP \fIn\fP \fB^[c\fP, \fB^[C\fP"
-Uppercase the first character in the next \fIn\fP words,
-leaving the cursor past the end of the last word.
-.\"}}}
-.\"{{{ comment ^[#
-If the current line does not begin with a comment character, one
-is added at the beginning of the line and the line is entered (as if
-return had been pressed), otherwise the existing comment characters
-are removed and the cursor is placed at the beginning of the line.
-.\"}}}
-.\"{{{ complete ^[^[
-.IP "\fBcomplete ^[^[\fP"
-Automatically completes as much as is unique of the command name
-or the file name containing the cursor. If the entire remaining command
-or file name is unique a space is printed after its completion, unless
-it is a directory name in which case \fB/\fP is appended. If there is
-no command or file name with the current partial word as its
-prefix, a bell character is output (usually causing a audio beep).
-.\"}}}
-.\"{{{ complete-command ^X^[
-.IP "\fBcomplete-command ^X^[\fP"
-Automatically completes as much as is unique of the command name
-having the partial word up to the cursor as its prefix, as in the
-\fBcomplete\fP command described above.
-.\"}}}
-.\"{{{ complete-file ^[^X
-.IP "\fBcomplete-file ^[^X\fP"
-Automatically completes as much as is unique of the file name having
-the partial word up to the cursor as its prefix, as in the
-\fBcomplete\fP command described above.
-.\"}}}
-.\"{{{ complete-list ^[=
-.IP "\fBcomplete-list ^[=\fP"
-List the possible completions for the current word.
-.\"}}}
-.\"{{{ delete-char-backward n ERASE, ^?, ^H
-.IP "\fBdelete-char-backward\fP \fIn\fP \fBERASE\fP, \fB^?\fP, \fB^H\fP"
-Deletes \fIn\fP characters before the cursor.
-.\"}}}
-.\"{{{ delete-char-forward n
-.IP "\fBdelete-char-forward\fP \fIn\fP"
-Deletes \fIn\fP characters after the cursor.
-.\"}}}
-.\"{{{ delete-word-backward n ^[ERASE, ^[^?, ^[^H, ^[h
-.IP "\fBdelete-word-backward\fP \fIn\fP \fB^[ERASE\fP, \fB^[^?\fP, \fB^[^H\fP, \fB^[h\fP"
-Deletes \fIn\fP words before the cursor.
-.\"}}}
-.\"{{{ delete-word-forward n ^[d
-.IP "\fBdelete-word-forward\fP \fIn\fP \fB^[d\fP"
-Deletes characters after the cursor up to the end of \fIn\fP words.
-.\"}}}
-.\"{{{ down-history n ^N
-.IP "\fBdown-history\fP \fIn\fP \fB^N\fP"
-Scrolls the history buffer forward \fIn\fP lines (later). Each input line
-originally starts just after the last entry in the history buffer, so
-\fBdown-history\fP is not useful until either \fBsearch-history\fP or
-\fBup-history\fP has been performed.
-.\"}}}
-.\"{{{ downcase-word n ^[L, ^[l
-.IP "\fBdowncase-word\fP \fIn\fP \fB^[L\fP, \fB^[l\fP"
-Lowercases the next \fIn\fP words.
-.\"}}}
-.\"{{{ end-of-history ^[>
-.IP "\fBend-of-history ^[>\fP"
-Moves to the end of the history.
-.\"}}}
-.\"{{{ end-of-line ^E
-.IP "\fBend-of-line ^E\fP"
-Moves the cursor to the end of the input line.
-.\"}}}
-.\"{{{ eot ^_
-.IP "\fBeot ^_\fP"
-Acts as an end-of-file; this is useful because edit-mode input disables
-normal terminal input canonicalization.
-.\"}}}
-.\"{{{ eot-or-delete n ^D
-.IP "\fBeot-or-delete\fP \fIn\fP \fB^D\fP"
-Acts as eot if alone on a line; otherwise acts as delete-char-forward.
-.\"}}}
-.\"{{{ error
-.IP "\fBerror\fP"
-Error (ring the bell).
-.\"}}}
-.\"{{{ exchange-point-and-mark ^X^X
-.IP "\fBexchange-point-and-mark ^X^X\fP"
-Places the cursor where the mark is, and sets the mark to where the
-cursor was.
-.\"}}}
-.\"{{{ expand-file ^[*
-.IP "\fBexpand-file ^[*\fP"
-Appends a * to the current word and replaces the word with
-the result of performing file globbing on the word.
-If no files match the pattern, the bell is rung.
-.\"}}}
-.\"{{{ forward-char n ^F
-.IP "\fBforward-char\fP \fIn\fP \fB^F\fP"
-Moves the cursor forward \fIn\fP characters.
-.\"}}}
-.\"{{{ forward-word n ^[f
-.IP "\fBforward-word\fP \fIn\fP \fB^[f\fP"
-Moves the cursor forward to the end of the \fIn\fPth word.
-.\"}}}
-.\"{{{ goto-history n ^[g
-.IP "\fBgoto-history\fP \fIn\fP \fB^[g\fP"
-Goes to history number \fIn\fP.
-.\"}}}
-.\"{{{ kill-line KILL
-.IP "\fBkill-line KILL\fP"
-Deletes the entire input line.
-.\"}}}
-.\"{{{ kill-region ^W
-.IP "\fBkill-region ^W\fP"
-Deletes the input between the cursor and the mark.
-.\"}}}
-.\"{{{ kill-to-eol n ^K
-.IP "\fBkill-to-eol\fP \fIn\fP \fB^K\fP"
-Deletes the input from the cursor to the end of the line if \fIn\fP is
-not specified, otherwise deletes characters between the cursor and
-column \fIn\fP.
-.\"}}}
-.\"{{{ list ^[?
-.IP "\fBlist ^[?\fP"
-Prints a sorted, columnated list of command names or file names
-(if any) that can complete the partial word containing the cursor.
-Directory names have \fB/\fP appended to them.
-.\"}}}
-.\"{{{ list-command ^X?
-.IP "\fBlist-command ^X?\fP"
-Prints a sorted, columnated list of command names (if any) that
-can complete the partial word containing the cursor.
-.\"}}}
-.\"{{{ list-file ^X^Y
-.IP "\fBlist-file ^X^Y\fP"
-Prints a sorted, columnated list of file names (if any) that can
-complete the partial word containing the cursor. File type indicators
-are appended as described under \fBlist\fP above.
-.\"}}}
-.\"{{{ newline ^J and ^M
-.IP "\fBnewline ^J\fP, \fB^M\fP"
-Causes the current input line to be processed by the shell. The
-current cursor position may be anywhere on the line.
-.\"}}}
-.\"{{{ newline-and-next ^O
-.IP "\fBnewline-and-next ^O\fP"
-Causes the current input line to be processed by the shell, and
-the next line from history becomes the current line. This is
-only useful after an up-history or search-history.
-.\"}}}
-.\"{{{ no-op QUIT
-.IP "\fBno-op QUIT\fP"
-This does nothing.
-.\"}}}
-.\"{{{ prefix-1 ^[
-.IP "\fBprefix-1 ^[\fP"
-Introduces a 2-character command sequence.
-.\"}}}
-.\"{{{ prefix-2 ^X and ^[[
-.IP "\fBprefix-2 ^X\fP"
-.IP "\fBprefix-2 ^[[\fP"
-Introduces a 2-character command sequence.
-.\"}}}
-.\"{{{ prev-hist-word ^[. ^[_
-.IP "\fBprev-hist-word\fP \fIn\fP \fB^[.\fP, \fB^[_\fP"
-The last (\fIn\fPth) word of the previous command is inserted at the cursor.
-.\"}}}
-.\"{{{ quote ^^
-.IP "\fBquote ^^\fP"
-The following character is taken literally rather than as an editing
-command.
-.\"}}}
-.\"{{{ redraw ^L
-.IP "\fBredraw ^L\fP"
-Reprints the prompt string and the current input line.
-.\"}}}
-.\"{{{ search-character-backward n ^[^]
-.IP "\fBsearch-character-backward\fP \fIn\fP \fB^[^]\fP"
-Search backward in the current line for the \fIn\fPth occurance of the
-next character typed.
-.\"}}}
-.\"{{{ search-character-forward n ^]
-.IP "\fBsearch-character-forward\fP \fIn\fP \fB^]\fP"
-Search forward in the current line for the \fIn\fPth occurance of the
-next character typed.
-.\"}}}
-.\"{{{ search-history ^R
-.IP "\fBsearch-history ^R\fP"
-Enter incremental search mode. The internal history list is searched
-backwards for commands matching the input. An initial \fB^\fP in the
-search string anchors the search. The abort key will leave search mode.
-Other commands will be executed after leaving search mode. Successive
-\fBsearch-history\fP commands continue searching backward to the next
-previous occurrence of the pattern. The history buffer retains only a
-finite number of lines; the oldest are discarded as necessary.
-.\"}}}
-.\"{{{ set-mark-command ^[<space>
-.IP "\fBset-mark-command ^[\fP<space>"
-Set the mark at the cursor position.
-.\"}}}
-.\"{{{ stuff
-.IP "\fBstuff\fP"
-On systems supporting it, pushes the bound character back onto the
-terminal input where it may receive special processing by the terminal
-handler. This is useful for the BRL \fB^T\fP mini-systat feature, for
-example.
-.\"}}}
-.\"{{{ stuff-reset
-.IP "\fBstuff-reset\fP"
-Acts like \fBstuff\fP, then aborts input the same as an interrupt.
-.\"}}}
-.\"{{{ transport-chars ^T
-.IP "\fBtranspose-chars ^T\fP"
-If at the end of line, or if the \fBgmacs\fP option is set,
-this exchanges the two previous characters; otherwise, it
-exchanges the previous and current characters and moves the cursor
-one character to the right.
-.\"}}}
-.\"{{{ up-history n ^P
-.IP "\fBup-history\fP \fIn\fP \fB^P\fP"
-Scrolls the history buffer backward \fIn\fP lines (earlier).
-.\"}}}
-.\"{{{ upcase-word n ^[U, ^[u
-.IP "\fBupcase-word\fP \fIn\fP \fB^[U\fP, \fB^[u\fP"
-Uppercases the next \fIn\fP words.
-.\"}}}
-.\"{{{ version ^V
-.IP "\fBversion ^V\fP"
-Display the version of ksh. The current edit buffer is restored as soon
-as any key is pressed (the key is then processed, unless it is a space).
-.\"}}}
-.\"{{{ yank ^Y
-.IP "\fByank ^Y\fP"
-Inserts the most recently killed text string at the current cursor position.
-.\"}}}
-.\"{{{ yank-pop ^[y
-.IP "\fByank-pop ^[y\fP"
-Immediately after a \fByank\fP, replaces the inserted text string with
-the next previous killed text string.
-.\"}}}
-.\"}}}
-.\"{{{ Vi Interactive Input Line Editing
-.\"{{{ introduction
-.SS "Vi Interactive Input Line Editing"
-The vi command line editor in ksh has basically the same commands as the
-vi editor (see \fIvi\fP(1)), with the following exceptions:
-.nr P2 \n(PD
-.IP \ \ \(bu
-you start out in insert mode,
-.IP \ \ \(bu
-there are file name and command completion commands
-(\fB=\fP, \fB\e\fP, \fB*\fP, \fB^X\fP, \fB^E\fP, \fB^F\fP and,
-optionally, \fB<tab>\fP),
-.IP \ \ \(bu
-the \fB_\fP command is different (in ksh it is the last argument command,
-in vi it goes to the start of the current line),
-.IP \ \ \(bu
-the \fB/\fP and \fBG\fP commands move in the opposite direction as the \fBj\fP
-command
-.IP \ \ \(bu
-and commands which don't make sense in a single line editor are not available
-(\fIe.g.\fP, screen movement commands, ex \fB:\fP commands, \fIetc.\fP).
-.nr PD \n(P2
-.LP
-Note that the \fB^X\fP stands for control-X; also \fB<esc>\fP, \fB<space>\fP
-and \fB<tab>\fP are used for escape, space and tab, respectively (no kidding).
-.\"}}}
-.\"{{{ modes
-.PP
-Like vi, there are two modes: insert mode and command mode.
-In insert mode, most characters are simply put in the buffer at the
-current cursor position as they are typed, however, some characters
-are treated specially.
-In particular, the following characters are taken from current tty settings
-(see \fIstty\fP(1)) and have their usual meaning (normal values are in
-parentheses):
-kill (\fB^U\fP), erase (\fB^?\fP), werase (\fB^W\fP), eof (\fB^D\fP),
-intr (\fB^C\fP) and quit (\fB^\e\fP).
-In addition to the above, the following characters are also treated
-specially in insert mode:
-.TS
-expand;
-afB lw(4.5i).
-^H T{
-erases previous character
-T}
-^V T{
-literal next: the next character typed is not treated specially (can be
-used to insert the characters being described here)
-T}
-^J ^M T{
-end of line: the current line is read, parsed and executed by the shell
-T}
-<esc> T{
-puts the editor in command mode (see below)
-T}
-^E T{
-command and file name enumeration (see below)
-T}
-^F T{
-command and file name completion (see below).
-If used twice in a row, the list of possible completions is displayed;
-if used a third time, the completion is undone.
-T}
-^X T{
-command and file name expansion (see below)
-T}
-<tab> T{
-optional file name and command completion (see \fB^F\fP above), enabled with
-\fBset \-o vi-tabcomplete\fP
-T}
-.TE
-.\"}}}
-.\"{{{ display
-.PP
-If a line is longer that the screen width (see \fBCOLUMNS\fP parameter),
-a \fB>\fP, \fB+\fP or \fB<\fP character is displayed in the last column
-indicating that there are more characters after, before and after, or
-before the current position, respectively.
-The line is scrolled horizontally as necessary.
-.\"}}}
-.\"{{{ command mode
-.PP
-In command mode, each character is interpreted as a command.
-Characters that don't correspond to commands, are illegal combinations of
-commands or are commands that can't be carried out all cause beeps.
-In the following command descriptions, a \fIn\fP indicates the
-command may be prefixed by a number (\fIe.g.\fP, \fB10l\fP moves right 10
-characters); if no number prefix is used, \fIn\fP is assumed to be 1
-unless otherwise specified.
-The term `current position' refers to the position between the cursor
-and the character preceding the cursor.
-A `word' is a sequence of letters, digits and underscore characters or a
-sequence of non-letter, non-digit, non-underscore, non-white-space characters
-(\fIe.g.\fP, ab2*&^ contains two words) and a `big-word' is a sequence of
-non-white-space characters.
-.\"{{{ Special ksh vi commands
-.IP "Special ksh vi commands"
-The following commands are not in, or are different from, the normal vi file
-editor:
-.RS
-.IP "\fIn\fP\fB_\fP"
-insert a space followed by the \fIn\fPth big-word from the last command in the
-history at the current position and enter insert mode; if \fIn\fP is not
-specified, the last word is inserted.
-.IP "\fB#\fP"
-insert the comment character (\fB#\fP) at the start of the current line and
-return the line to the shell (equivalent to \fBI#^J\fP).
-.IP "\fIn\fP\fBg\fP"
-like \fBG\fP, except if \fIn\fP is not specified, it goes to the most recent
-remembered line.
-.IP "\fIn\fP\fBv\fP"
-edit line \fIn\fP using the vi editor;
-if \fIn\fP is not specified, the current line is edited.
-The actual command executed is
-`\fBfc \-e ${VISUAL:-${EDITOR:-vi}}\fP \fIn\fP'.
-.IP "\fB*\fP and \fB^X\fP"
-command or file name expansion is applied to the current big-word
-(with an appended *, if the word contains no file globing characters) - the
-big-word is replaced with the resulting words.
-If the current big-word is the first on the line (or follows one
-of the following characters: \fB;\fP, \fB|\fP, \fB&\fP, \fB(\fP, \fB)\fP)
-and does not contain a slash (\fB/\fP) then command expansion is done,
-otherwise file name expansion is done.
-Command expansion will match the big-word against all aliases, functions
-and built-in commands as well as any executable files found by searching
-the directories in the \fBPATH\fP parameter.
-File name expansion matches the big-word against the files in the
-current directory.
-After expansion, the cursor is placed just past the last word and the editor
-is in insert mode.
-.IP "\fIn\fP\fB\e\fP, \fIn\fP\fB^F\fP, \fIn\fP\fB<tab>\fP and \fIn\fP\fB<esc>\fP"
-command/file name completion:
-replace the current big-word with the longest unique
-match obtained after performing command/file name expansion.
-\fB<tab>\fP is only recognized if the \fBvi-tabcomplete\fP option is set,
-while \fB<esc>\fP is only recognized if the \fBvi-esccomplete\fP option
-is set (see \fBset \-o\fP).
-If \fIn\fP is specified, the \fIn\fPth possible
-completion is selected (as reported by the command/file name enumeration
-command).
-.IP "\fB=\fP and \fB^E\fP"
-command/file name enumeration: list all the commands or files that match
-the current big-word.
-.IP "\fB^V\fP"
-display the version of pdksh; it is displayed until another key is pressed
-(this key is ignored).
-.IP "\fB@\fP\fIc\fP"
-macro expansion: execute the commands found in the alias _\fIc\fP.
-.RE
-.\"}}}
-.\"{{{ Intra-line movement commands
-.IP "Intra-line movement commands"
-.RS
-.IP "\fIn\fP\fBh\fP and \fIn\fP\fB^H\fP"
-move left \fIn\fP characters.
-.IP "\fIn\fP\fBl\fP and \fIn\fP\fB<space>\fP"
-move right \fIn\fP characters.
-.IP "\fB0\fP"
-move to column 0.
-.IP "\fB^\fP"
-move to the first non white-space character.
-.IP "\fIn\fP\fB|\fP"
-move to column \fIn\fP.
-.IP "\fB$\fP"
-move to the last character.
-.IP "\fIn\fP\fBb\fP"
-move back \fIn\fP words.
-.IP "\fIn\fP\fBB\fP"
-move back \fIn\fP big-words.
-.IP "\fIn\fP\fBe\fP"
-move forward to the end the word, \fIn\fP times.
-.IP "\fIn\fP\fBE\fP"
-move forward to the end the big-word, \fIn\fP times.
-.IP "\fIn\fP\fBw\fP"
-move forward \fIn\fP words.
-.IP "\fIn\fP\fBW\fP"
-move forward \fIn\fP big-words.
-.IP "\fB%\fP"
-find match: the editor looks forward for the nearest parenthesis,
-bracket or brace and then moves the to the matching parenthesis, bracket or
-brace.
-.IP "\fIn\fP\fBf\fP\fIc\fP"
-move forward to the \fIn\fPth occurrence of the character \fIc\fP.
-.IP "\fIn\fP\fBF\fP\fIc\fP"
-move backward to the \fIn\fPth occurrence of the character \fIc\fP.
-.IP "\fIn\fP\fBt\fP\fIc\fP"
-move forward to just before the \fIn\fPth occurrence of the character \fIc\fP.
-.IP "\fIn\fP\fBT\fP\fIc\fP"
-move backward to just before the \fIn\fPth occurrence of the character \fIc\fP.
-.IP "\fIn\fP\fB;\fP"
-repeats the last \fBf\fP, \fBF\fP, \fBt\fP or \fBT\fP command.
-.IP "\fIn\fP\fB,\fP"
-repeats the last \fBf\fP, \fBF\fP, \fBt\fP or \fBT\fP command, but moves
-in the opposite direction.
-.RE
-.\"}}}
-.\"{{{ Inter-line movement commands
-.IP "Inter-line movement commands"
-.RS
-.IP "\fIn\fP\fBj\fP and \fIn\fP\fB+\fP and \fIn\fP\fB^N\fP"
-move to the \fIn\fPth next line in the history.
-.IP "\fIn\fP\fBk\fP and \fIn\fP\fB-\fP and \fIn\fP\fB^P\fP"
-move to the \fIn\fPth previous line in the history.
-.IP "\fIn\fP\fBG\fP"
-move to line \fIn\fP in the history; if \fIn\fP is not specified, the
-number first remembered line is used.
-.IP "\fIn\fP\fBg\fP"
-like \fBG\fP, except if \fIn\fP is not specified, it goes to the most recent
-remembered line.
-.IP "\fIn\fP\fB/\fP\fIstring\fP"
-search backward through the history for the \fIn\fPth line containing
-\fIstring\fP; if \fIstring\fP starts with \fB^\fP, the remainder of the
-string must appear at the start of the history line for it to match.
-.IP "\fIn\fP\fB?\fP\fIstring\fP"
-same as \fB/\fP, except it searches forward through the history.
-.IP "\fIn\fP\fBn\fP"
-search for the \fIn\fPth occurrence of the last search string; the
-direction of the search is the same as the last search.
-.IP "\fIn\fP\fBN\fP"
-search for the \fIn\fPth occurrence of the last search string; the
-direction of the search is the opposite of the last search.
-.RE
-.\"}}}
-.\"{{{ Edit commands
-.IP "Edit commands"
-.RS
-.IP "\fIn\fP\fBa\fP"
-append text \fIn\fP times: goes into insert mode just after the current
-position.
-The append is only replicated if command mode is re-entered (\fIi.e.\fP,
-<esc> is used).
-.IP "\fIn\fP\fBA\fP"
-same as \fBa\fP, except it appends at the end of the line.
-.IP "\fIn\fP\fBi\fP"
-insert text \fIn\fP times: goes into insert mode at the current
-position.
-The insertion is only replicated if command mode is re-entered (\fIi.e.\fP,
-<esc> is used).
-.IP "\fIn\fP\fBI\fP"
-same as \fBi\fP, except the insertion is done just before the first non-blank
-character.
-.IP "\fIn\fP\fBs\fP"
-substitute the next \fIn\fP characters (\fIi.e.\fP, delete the characters
-and go into insert mode).
-.IP "\fBS\fP"
-substitute whole line: all characters from the first non-blank character
-to the end of line are deleted and insert mode is entered.
-.IP "\fIn\fP\fBc\fP\fImove-cmd\fP"
-change from the current position to the position resulting from \fIn\fP
-\fImove-cmd\fPs (\fIi.e.\fP, delete the indicated region and go into insert
-mode);
-if \fImove-cmd\fP is \fBc\fP, the line starting from the first non-blank
-character is changed.
-.IP "\fBC\fP"
-change from the current position to the end of the line (\fIi.e.\fP, delete to
-the end of the line and go into insert mode).
-.IP "\fIn\fP\fBx\fP"
-delete the next \fIn\fP characters.
-.IP "\fIn\fP\fBX\fP"
-delete the previous \fIn\fP characters.
-.IP "\fBD\fP"
-delete to the end of the line.
-.IP "\fIn\fP\fBd\fP\fImove-cmd\fP"
-delete from the current position to the position resulting from
-\fIn\fP \fImove-cmd\fPs;
-\fImove-cmd\fP is a movement command (see above) or \fBd\fP, in which case
-the current line is deleted.
-.IP "\fIn\fP\fBr\fP\fIc\fP"
-replace the next \fIn\fP characters with the character \fIc\fP.
-.IP "\fIn\fP\fBR\fP"
-replace: enter insert mode but overwrite existing characters instead of
-inserting before existing characters. The replacement is repeated \fIn\fP
-times.
-.IP "\fIn\fP\fB~\fP"
-change the case of the next \fIn\fP characters.
-.IP "\fIn\fP\fBy\fP\fImove-cmd\fP"
-yank from the current position to the position resulting from \fIn\fP
-\fImove-cmd\fPs into the yank buffer; if \fImove-cmd\fP is \fBy\fP, the
-whole line is yanked.
-.IP "\fBY\fP"
-yank from the current position to the end of the line.
-.IP "\fIn\fP\fBp\fP"
-paste the contents of the yank buffer just after the current position,
-\fIn\fP times.
-.IP "\fIn\fP\fBP\fP"
-same as \fBp\fP, except the buffer is pasted at the current position.
-.RE
-.\"}}}
-.\"{{{ Miscellaneous vi commands
-.IP "Miscellaneous vi commands"
-.RS
-.IP "\fB^J\fP and \fB^M\fP"
-the current line is read, parsed and executed by the shell.
-.IP "\fB^L\fP and \fB^R\fP"
-redraw the current line.
-.IP "\fIn\fP\fB.\fP"
-redo the last edit command \fIn\fP times.
-.IP "\fBu\fP"
-undo the last edit command.
-.IP "\fBU\fP"
-undo all changes that have been made to the current line.
-.IP "\fIintr\fP and \fIquit\fP"
-the interrupt and quit terminal characters cause the current line to
-be deleted and a new prompt to be printed.
-.RE
-.\"Has all vi commands except:
-.\" movement: { } [[ ]] ^E ^Y ^U ^D ^F ^B H L M ()
-.\" tag commands: ^T ^]
-.\" mark commands: m ` '
-.\" named-buffer commands: " @
-.\" file/shell/ex-commands: Q ZZ ^^ : ! &
-.\" multi-line change commands: o O J
-.\" shift commands: << >>
-.\" status command: ^G
-.\"}}}
-.\"}}}
-.\"}}}
-.\"}}}
-.\"{{{ Files
-.SH FILES
-~/.profile
-.br
-/etc/profile
-.br
-/etc/suid_profile
-.\"}}}
-.\"{{{ Bugs
-.SH BUGS
-Any bugs in pdksh should be reported to pdksh@cs.mun.ca. Please
-include the version of pdksh (echo $KSH_VERSION shows it), the machine,
-operating system and compiler you are using and a description of how to
-repeat the bug (a small shell script that demonstrates the bug is
-best). The following, if relevant (if you are not sure, include them),
-can also helpful: options you are using (both options.h options and set
-\-o options) and a copy of your config.h (the file generated by the
-configure script). New versions of pdksh can be obtained from
-ftp.cs.mun.ca:pub/pdksh/.
-.\"}}}
-.\"{{{ Authors
-.SH AUTHORS
-This shell is based on the public domain 7th edition Bourne shell clone by
-Charles Forsyth and parts of the BRL shell by Doug A.\& Gwyn, Doug Kingston,
-Ron Natalie, Arnold Robbins, Lou Salkind and others. The first release
-was created by Eric Gisin, and it was subsequently maintained by
-John R.\& MacMillan (chance!john@sq.sq.com), and
-Simon J.\& Gerraty (sjg@zen.void.oz.au). The current maintainer is
-Michael Rendell (michael@cs.mun.ca).
-The CONTRIBUTORS file in the source distribution contains a more complete
-list of people and their part in the shell's development.
-.\"}}}
-.\"{{{ See also
-.SH "SEE ALSO"
-awk(1),
-sh(1),
-csh(1), ed(1), getconf(1), getopt(1), sed(1), stty(1), vi(1),
-dup(2), execve(2), getgid(2), getuid(2), open(2), pipe(2), wait(2),
-getopt(3), rand(3), signal(3), system(3),
-environ(5)
-.PP
-.IR "The KornShell Command and Programming Language" ,
-Morris Bolsky and David Korn, 1989, ISBN 0-13-516972-0.
-.PP
-.\" XXX ISBN missing
-.IR "UNIX Shell Programming" ,
-Stephen G.\& Kochan, Patrick H.\& Wood, Hayden.
-.PP
-.IR "IEEE Standard for information Technology \- Portable Operating System Interface (POSIX) \- Part 2: Shell and Utilities" ,
-IEEE Inc, 1993, ISBN 1-55937-255-9.
-.\"}}}
diff --git a/bin/pdksh/ksh_dir.h b/bin/pdksh/ksh_dir.h
deleted file mode 100644
index 34c981fedc1..00000000000
--- a/bin/pdksh/ksh_dir.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* $OpenBSD: ksh_dir.h,v 1.1 1996/08/14 06:19:11 downsj Exp $ */
-
-/* Wrapper around the ugly dir includes/ifdefs */
-
-#if defined(HAVE_DIRENT_H)
-# include <dirent.h>
-# define NLENGTH(dirent) (strlen(dirent->d_name))
-#else
-# define dirent direct
-# define NLENGTH(dirent) (dirent->d_namlen)
-# ifdef HAVE_SYS_NDIR_H
-# include <sys/ndir.h>
-# endif /* HAVE_SYS_NDIR_H */
-# ifdef HAVE_SYS_DIR_H
-# include <sys/dir.h>
-# endif /* HAVE_SYSDIR_H */
-# ifdef HAVE_NDIR_H
-# include <ndir.h>
-# endif /* HAVE_NDIR_H */
-#endif /* HAVE_DIRENT_H */
-
-#ifdef OPENDIR_DOES_NONDIR
-extern DIR *ksh_opendir ARGS((const char *d));
-#else /* OPENDIR_DOES_NONDIR */
-# define ksh_opendir(d) opendir(d)
-#endif /* OPENDIR_DOES_NONDIR */
diff --git a/bin/pdksh/ksh_limval.h b/bin/pdksh/ksh_limval.h
deleted file mode 100644
index 828c0f82577..00000000000
--- a/bin/pdksh/ksh_limval.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* $OpenBSD: ksh_limval.h,v 1.1 1996/08/14 06:19:11 downsj Exp $ */
-
-/* Wrapper around the values.h/limits.h includes/ifdefs */
-
-#ifdef HAVE_VALUES_H
-# include <values.h>
-#endif /* HAVE_VALUES_H */
-/* limits.h is included in sh.h */
-
-#ifndef DMAXEXP
-# define DMAXEXP 128 /* should be big enough */
-#endif
-
-#ifndef BITSPERBYTE
-# ifdef CHAR_BIT
-# define BITSPERBYTE CHAR_BIT
-# else
-# define BITSPERBYTE 8 /* probably true.. */
-# endif
-#endif
-
-#ifndef BITS
-# define BITS(t) (BITSPERBYTE * sizeof(t))
-#endif
diff --git a/bin/pdksh/ksh_stat.h b/bin/pdksh/ksh_stat.h
deleted file mode 100644
index 1abcc7cb1fc..00000000000
--- a/bin/pdksh/ksh_stat.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/* $OpenBSD: ksh_stat.h,v 1.3 1996/10/01 02:05:39 downsj Exp $ */
-
-/* Wrapper around the ugly sys/stat includes/ifdefs */
-
-/* assumes <sys/types.h> already included */
-#include <sys/stat.h>
-
-#ifndef HAVE_LSTAT
-# define lstat(path, buf) stat(path, buf)
-#endif /* HAVE_LSTAT */
-
-#ifdef STAT_MACROS_BROKEN
-# undef S_ISREG
-# undef S_ISDIR
-# undef S_ISCHR
-# undef S_ISBLK
-# undef S_ISFIFO
-# undef S_ISSOCK
-# undef S_ISLNK
-#endif /* STAT_MACROS_BROKEN */
-
-#if !defined(S_ISREG) && defined(S_IFREG)
-# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
-#endif /* S_ISREG */
-#if !defined(S_ISDIR) && defined(S_IFDIR)
-# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
-#endif /* S_ISDIR */
-#if !defined(S_ISCHR) && defined(S_IFCHR)
-# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
-#endif /* S_ISCHR */
-#if !defined(S_ISBLK) && defined(S_IFBLK)
-# define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
-#endif /* S_ISBLK */
-#if !defined(S_ISFIFO) && defined(S_IFIFO)
-# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
-#endif /* S_ISFIFO */
-#if !defined(S_ISLNK) && defined(S_IFLNK)
-# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
-#endif /* S_ISLNK */
-#if !defined(S_ISSOCK) && defined(S_IFSOCK)
-# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
-#endif /* S_ISSOCK */
-#if !defined(S_ISCDF) && defined(S_CDF)
-# define S_ISCDF(m) (S_ISDIR(m) && ((m) & S_CDF))
-#endif /* S_ISSOCK */
-
-#ifndef S_ISVTX
-# define S_ISVTX 01000 /* sticky bit */
-#endif /* S_ISVTX */
-
-#ifndef S_IXUSR
-# define S_IXUSR 00100 /* user execute bit */
-#endif /* S_IXUSR */
-#ifndef S_IXGRP
-# define S_IXGRP 00010 /* user execute bit */
-#endif /* S_IXGRP */
-#ifndef S_IXOTH
-# define S_IXOTH 00001 /* user execute bit */
-#endif /* S_IXOTH */
diff --git a/bin/pdksh/ksh_time.h b/bin/pdksh/ksh_time.h
deleted file mode 100644
index ee8dc9b9128..00000000000
--- a/bin/pdksh/ksh_time.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* $OpenBSD: ksh_time.h,v 1.2 1996/10/01 02:05:40 downsj Exp $ */
-
-#ifndef KSH_TIME_H
-# define KSH_TIME_H
-
-/* Wrapper around the ugly time.h,sys/time.h includes/ifdefs */
-
-#ifdef TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else /* TIME_WITH_SYS_TIME */
-# ifdef HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif /* TIME_WITH_SYS_TIME */
-
-#ifndef TIME_DECLARED
-extern time_t time ARGS((time_t *));
-#endif
-
-#ifndef CLK_TCK
-# define CLK_TCK 60 /* 60HZ */
-#endif
-#endif /* KSH_TIME_H */
diff --git a/bin/pdksh/ksh_times.h b/bin/pdksh/ksh_times.h
deleted file mode 100644
index ec7b97eedf5..00000000000
--- a/bin/pdksh/ksh_times.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/* $OpenBSD: ksh_times.h,v 1.2 1996/10/01 02:05:41 downsj Exp $ */
-
-#ifndef KSH_TIMES_H
-# define KSH_TIMES_H
-
-/* Needed for clock_t on some systems (ie, NeXT in non-posix mode) */
-#include "ksh_time.h"
-
-#include <sys/times.h>
-
-#ifdef TIMES_BROKEN
-extern clock_t ksh_times ARGS((struct tms *));
-#else /* TIMES_BROKEN */
-# define ksh_times times
-#endif /* TIMES_BROKEN */
-
-#ifdef HAVE_TIMES
-extern clock_t times ARGS((struct tms *));
-#endif /* HAVE_TIMES */
-#endif /* KSH_TIMES_H */
diff --git a/bin/pdksh/ksh_wait.h b/bin/pdksh/ksh_wait.h
deleted file mode 100644
index a077b90f16b..00000000000
--- a/bin/pdksh/ksh_wait.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/* $OpenBSD: ksh_wait.h,v 1.3 1997/06/19 13:58:43 kstailey Exp $ */
-
-/* Wrapper around the ugly sys/wait includes/ifdefs */
-
-#ifdef HAVE_SYS_WAIT_H
-# include <sys/wait.h>
-#endif
-
-#ifndef POSIX_SYS_WAIT
-/* Get rid of system macros (which probably use union wait) */
-# undef WIFCORED
-# undef WIFEXITED
-# undef WEXITSTATUS
-# undef WIFSIGNALED
-# undef WTERMSIG
-# undef WIFSTOPPED
-# undef WSTOPSIG
-#endif /* POSIX_SYS_WAIT */
-
-typedef int WAIT_T;
-
-#ifndef WIFCORED
-# define WIFCORED(s) ((s) & 0x80)
-#endif
-#define WSTATUS(s) (s)
-
-#ifndef WIFEXITED
-# define WIFEXITED(s) (((s) & 0xff) == 0)
-#endif
-#ifndef WEXITSTATUS
-# define WEXITSTATUS(s) (((s) >> 8) & 0xff)
-#endif
-#ifndef WIFSIGNALED
-# define WIFSIGNALED(s) (((s) & 0xff) != 0 && ((s) & 0xff) != 0x7f)
-#endif
-#ifndef WTERMSIG
-# define WTERMSIG(s) ((s) & 0x7f)
-#endif
-#ifndef WIFSTOPPED
-# define WIFSTOPPED(s) (((s) & 0xff) == 0x7f)
-#endif
-#ifndef WSTOPSIG
-# define WSTOPSIG(s) (((s) >> 8) & 0xff)
-#endif
-
-#if !defined(HAVE_WAITPID) && defined(HAVE_WAIT3)
- /* always used with p == -1 */
-# define ksh_waitpid(p, s, o) wait3((s), (o), (struct rusage *) 0)
-#else /* !HAVE_WAITPID && HAVE_WAIT3 */
-# define ksh_waitpid(p, s, o) waitpid((p), (s), (o))
-#endif /* !HAVE_WAITPID && HAVE_WAIT3 */
diff --git a/bin/pdksh/lex.c b/bin/pdksh/lex.c
deleted file mode 100644
index 5db0c81accd..00000000000
--- a/bin/pdksh/lex.c
+++ /dev/null
@@ -1,1281 +0,0 @@
-/* $OpenBSD: lex.c,v 1.10 1997/09/12 04:39:32 millert Exp $ */
-
-/*
- * lexical analysis and source input
- */
-
-#include "sh.h"
-#include <ctype.h>
-
-static void readhere ARGS((struct ioword *iop));
-static int getsc__ ARGS((void));
-static void getsc_line ARGS((Source *s));
-static char *get_brace_var ARGS((XString *wsp, char *wp));
-static int arraysub ARGS((char **strp));
-static const char *ungetsc ARGS((int c));
-static int getsc_bn ARGS((void));
-static void gethere ARGS((void));
-
-static int backslash_skip;
-static int ignore_backslash_newline;
-
-/* optimized getsc_bn() */
-#define getsc() (*source->str != '\0' && *source->str != '\\' \
- && !backslash_skip ? *source->str++ : getsc_bn())
-/* optimized getsc__() */
-#define getsc_() ((*source->str != '\0') ? *source->str++ : getsc__())
-
-
-/*
- * Lexical analyzer
- *
- * tokens are not regular expressions, they are LL(1).
- * for example, "${var:-${PWD}}", and "$(size $(whence ksh))".
- * hence the state stack.
- */
-
-int
-yylex(cf)
- int cf;
-{
- register int c, state;
- char states [64], *statep = states; /* XXX overflow check */
- XString ws; /* expandable output word */
- register char *wp; /* output word pointer */
- register char *sp, *dp;
- char UNINITIALIZED(*ddparen_start);
- int istate;
- int UNINITIALIZED(c2);
- int UNINITIALIZED(nparen), UNINITIALIZED(csstate);
- int UNINITIALIZED(ndparen);
- int UNINITIALIZED(indquotes);
-
-
- Again:
- Xinit(ws, wp, 64, ATEMP);
-
- backslash_skip = 0;
- ignore_backslash_newline = 0;
-
- if (cf&ONEWORD)
- istate = SWORD;
-#ifdef KSH
- else if (cf&LETEXPR) {
- *wp++ = OQUOTE; /* enclose arguments in (double) quotes */
- istate = SDPAREN;
- ndparen = 0;
- }
-#endif /* KSH */
- else { /* normal lexing */
- istate = (cf & HEREDELIM) ? SHEREDELIM : SBASE;
- while ((c = getsc()) == ' ' || c == '\t')
- ;
- if (c == '#') {
- ignore_backslash_newline++;
- while ((c = getsc()) != '\0' && c != '\n')
- ;
- ignore_backslash_newline--;
- }
- ungetsc(c);
- }
- if (source->flags & SF_ALIAS) { /* trailing ' ' in alias definition */
- source->flags &= ~SF_ALIAS;
- /* In POSIX mode, a trailing space only counts if we are
- * parsing a simple command
- */
- if (!Flag(FPOSIX) || (cf & CMDWORD))
- cf |= ALIAS;
- }
-
- /* collect non-special or quoted characters to form word */
- for (*statep = state = istate;
- !((c = getsc()) == 0 || ((state == SBASE || state == SHEREDELIM)
- && ctype(c, C_LEX1))); )
- {
- Xcheck(ws, wp);
- switch (state) {
- case SBASE:
- if (c == '[' && (cf & (VARASN|ARRAYVAR))) {
- *wp = EOS; /* temporary */
- if (is_wdvarname(Xstring(ws, wp), FALSE))
- {
- char *p, *tmp;
-
- if (arraysub(&tmp)) {
- *wp++ = CHAR;
- *wp++ = c;
- for (p = tmp; *p; ) {
- Xcheck(ws, wp);
- *wp++ = CHAR;
- *wp++ = *p++;
- }
- afree(tmp, ATEMP);
- break;
- } else {
- Source *s;
-
- s = pushs(SREREAD,
- source->areap);
- s->start = s->str
- = s->u.freeme = tmp;
- s->next = source;
- source = s;
- }
- }
- *wp++ = CHAR;
- *wp++ = c;
- break;
- }
- /* fall through.. */
- Sbase1: /* includes *(...|...) pattern (*+?@!) */
-#ifdef KSH
- if (c == '*' || c == '@' || c == '+' || c == '?'
- || c == '!')
- {
- c2 = getsc();
- if (c2 == '(' /*)*/ ) {
- *wp++ = OPAT;
- *wp++ = c;
- *++statep = state = SPATTERN;
- break;
- }
- ungetsc(c2);
- }
-#endif /* KSH */
- /* fall through.. */
- Sbase2: /* doesn't include *(...|...) pattern (*+?@!) */
- switch (c) {
- case '\\':
- c = getsc();
-#ifdef OS2
- if (isalnum(c)) {
- *wp++ = CHAR, *wp++ = '\\';
- *wp++ = CHAR, *wp++ = c;
- } else
-#endif
- if (c) /* trailing \ is lost */
- *wp++ = QCHAR, *wp++ = c;
- break;
- case '\'':
- *++statep = state = SSQUOTE;
- *wp++ = OQUOTE;
- ignore_backslash_newline++;
- break;
- case '"':
- *++statep = state = SDQUOTE;
- *wp++ = OQUOTE;
- break;
- default:
- goto Subst;
- }
- break;
-
- Subst:
- switch (c) {
- case '\\':
- c = getsc();
- switch (c) {
- case '"': case '\\':
- case '$': case '`':
- *wp++ = QCHAR, *wp++ = c;
- break;
- default:
- Xcheck(ws, wp);
- if (c) { /* trailing \ is lost */
- *wp++ = CHAR, *wp++ = '\\';
- *wp++ = CHAR, *wp++ = c;
- }
- break;
- }
- break;
- case '$':
- c = getsc();
- if (c == '(') /*)*/ {
- c = getsc();
- if (c == '(') /*)*/ {
- *++statep = state = SDDPAREN;
- nparen = 2;
- ddparen_start = wp;
- *wp++ = EXPRSUB;
- } else {
- ungetsc(c);
- *++statep = state = SPAREN;
- nparen = 1;
- csstate = 0;
- *wp++ = COMSUB;
- }
- } else if (c == '{') /*}*/ {
- *wp++ = OSUBST;
- wp = get_brace_var(&ws, wp);
- /* If this is a trim operation,
- * wrap @(...) around the pattern
- * (allows easy handling of ${a#b|c})
- */
- c = getsc();
- if (c == '#' || c == '%') {
- *wp++ = CHAR, *wp++ = c;
- if ((c2 = getsc()) == c)
- *wp++ = CHAR, *wp++ = c;
- else
- ungetsc(c2);
- *wp++ = OPAT, *wp++ = '@';
- *++statep = state = STBRACE;
- } else {
- ungetsc(c);
- *++statep = state = SBRACE;
- }
- } else if (ctype(c, C_ALPHA)) {
- *wp++ = OSUBST;
- do {
- Xcheck(ws, wp);
- *wp++ = c;
- c = getsc();
- } while (ctype(c, C_ALPHA|C_DIGIT));
- *wp++ = '\0';
- *wp++ = CSUBST;
- ungetsc(c);
- } else if (ctype(c, C_DIGIT|C_VAR1)) {
- Xcheck(ws, wp);
- *wp++ = OSUBST;
- *wp++ = c;
- *wp++ = '\0';
- *wp++ = CSUBST;
- } else {
- *wp++ = CHAR, *wp++ = '$';
- ungetsc(c);
- }
- break;
- case '`':
- *++statep = state = SBQUOTE;
- *wp++ = COMSUB;
- /* Need to know if we are inside double quotes
- * since sh/at&t-ksh translate the \" to " in
- * "`..\"..`".
- */
- indquotes = 0;
- if (!Flag(FPOSIX))
- for (sp = statep; sp > states; --sp)
- if (*sp == SDQUOTE)
- indquotes = 1;
- break;
- default:
- *wp++ = CHAR, *wp++ = c;
- }
- break;
-
- case SSQUOTE:
- if (c == '\'') {
- state = *--statep;
- *wp++ = CQUOTE;
- ignore_backslash_newline--;
- } else
- *wp++ = QCHAR, *wp++ = c;
- break;
-
- case SDQUOTE:
- if (c == '"') {
- state = *--statep;
- *wp++ = CQUOTE;
- } else
- goto Subst;
- break;
-
- case SPAREN: /* $( .. ) */
- /* todo: deal with $(...) quoting properly
- * kludge to partly fake quoting inside $(..): doesn't
- * really work because nested $(..) or ${..} inside
- * double quotes aren't dealt with.
- */
- switch (csstate) {
- case 0: /* normal */
- switch (c) {
- case '(':
- nparen++;
- break;
- case ')':
- nparen--;
- break;
- case '\\':
- csstate = 1;
- break;
- case '"':
- csstate = 2;
- break;
- case '\'':
- csstate = 4;
- ignore_backslash_newline++;
- break;
- }
- break;
-
- case 1: /* backslash in normal mode */
- case 3: /* backslash in double quotes */
- --csstate;
- break;
-
- case 2: /* double quotes */
- if (c == '"')
- csstate = 0;
- else if (c == '\\')
- csstate = 3;
- break;
-
- case 4: /* single quotes */
- if (c == '\'') {
- csstate = 0;
- ignore_backslash_newline--;
- }
- break;
- }
- if (nparen == 0) {
- state = *--statep;
- *wp++ = 0; /* end of COMSUB */
- } else
- *wp++ = c;
- break;
-
- case SDDPAREN: /* $(( .. )) */
- /* todo: deal with $((...); (...)) properly */
- /* XXX should nest using existing state machine
- * (embed "..", $(...), etc.) */
- if (c == '(')
- nparen++;
- else if (c == ')') {
- nparen--;
- if (nparen == 1) {
- /*(*/
- if ((c2 = getsc()) == ')') {
- state = *--statep;
- *wp++ = 0; /* end of EXPRSUB */
- break;
- } else {
- ungetsc(c2);
- /* mismatched parenthesis -
- * assume we were really
- * parsing a $(..) expression
- */
- memmove(ddparen_start + 1,
- ddparen_start,
- wp - ddparen_start);
- *ddparen_start++ = COMSUB;
- *ddparen_start = '('; /*)*/
- wp++;
- csstate = 0;
- *statep = state = SPAREN;
- }
- }
- }
- *wp++ = c;
- break;
-
- case SBRACE:
- /*{*/
- if (c == '}') {
- state = *--statep;
- *wp++ = CSUBST;
- } else
- goto Sbase1;
- break;
-
- case STBRACE:
- /* same as SBRACE, except | is saved as SPAT and
- * CPAT is added at the end.
- */
- /*{*/
- if (c == '}') {
- state = *--statep;
- *wp++ = CPAT;
- *wp++ = CSUBST;
- } else if (c == '|') {
- *wp++ = SPAT;
- } else
- goto Sbase1;
- break;
-
- case SBQUOTE:
- if (c == '`') {
- *wp++ = 0;
- state = *--statep;
- } else if (c == '\\') {
- switch (c = getsc()) {
- case '\\':
- case '$': case '`':
- *wp++ = c;
- break;
- case '"':
- if (indquotes) {
- *wp++ = c;
- break;
- }
- /* fall through.. */
- default:
- if (c) { /* trailing \ is lost */
- *wp++ = '\\';
- *wp++ = c;
- }
- break;
- }
- } else
- *wp++ = c;
- break;
-
- case SWORD: /* ONEWORD */
- goto Subst;
-
-#ifdef KSH
- case SDPAREN: /* LETEXPR: (( ... )) */
- /*(*/
- if (c == ')') {
- if (ndparen > 0)
- --ndparen;
- /*(*/
- else if ((c2 = getsc()) == ')') {
- c = 0;
- *wp++ = CQUOTE;
- goto Done;
- } else
- ungetsc(c2);
- } else if (c == '(')
- /* parenthesis inside quotes and backslashes
- * are lost, but at&t ksh doesn't count them
- * either
- */
- ++ndparen;
- goto Sbase2;
-#endif /* KSH */
-
- case SHEREDELIM: /* <<,<<- delimiter */
- /* XXX chuck this state (and the next) - use
- * the existing states ($ and \`..` should be
- * stripped of their specialness after the
- * fact).
- */
- /* here delimiters need a special case since
- * $ and `..` are not to be treated specially
- */
- if (c == '\\') {
- c = getsc();
- if (c) { /* trailing \ is lost */
- *wp++ = QCHAR;
- *wp++ = c;
- }
- } else if (c == '\'') {
- *++statep = state = SSQUOTE;
- *wp++ = OQUOTE;
- ignore_backslash_newline++;
- } else if (c == '"') {
- state = SHEREDQUOTE;
- *wp++ = OQUOTE;
- } else {
- *wp++ = CHAR;
- *wp++ = c;
- }
- break;
-
- case SHEREDQUOTE: /* " in <<,<<- delimiter */
- if (c == '"') {
- *wp++ = CQUOTE;
- state = SHEREDELIM;
- } else {
- if (c == '\\') {
- switch (c = getsc()) {
- case '\\': case '"':
- case '$': case '`':
- break;
- default:
- if (c) { /* trailing \ lost */
- *wp++ = CHAR;
- *wp++ = '\\';
- }
- break;
- }
- }
- *wp++ = CHAR;
- *wp++ = c;
- }
- break;
-
- case SPATTERN: /* in *(...|...) pattern (*+?@!) */
- if ( /*(*/ c == ')') {
- *wp++ = CPAT;
- state = *--statep;
- } else if (c == '|')
- *wp++ = SPAT;
- else
- goto Sbase1;
- break;
- }
- }
-Done:
- Xcheck(ws, wp);
- if (state != istate)
- yyerror("no closing quote\n");
-
- /* This done to avoid tests for SHEREDELIM wherever SBASE tested */
- if (state == SHEREDELIM)
- state = SBASE;
-
- if ((c == '<' || c == '>') && state == SBASE) {
- char *cp = Xstring(ws, wp);
- if (Xlength(ws, wp) == 2 && cp[0] == CHAR && digit(cp[1])) {
- wp = cp; /* throw away word */
- c2/*unit*/ = cp[1] - '0';
- } else
- c2/*unit*/ = c == '>'; /* 0 for <, 1 for > */
- }
-
- if (wp == Xstring(ws, wp) && state == SBASE) {
- Xfree(ws, wp); /* free word */
- /* no word, process LEX1 character */
- switch (c) {
- default:
- return c;
-
- case '|':
- case '&':
- case ';':
- if ((c2 = getsc()) == c)
- c = (c == ';') ? BREAK :
- (c == '|') ? LOGOR :
- (c == '&') ? LOGAND :
- YYERRCODE;
-#ifdef KSH
- else if (c == '|' && c2 == '&')
- c = COPROC;
-#endif /* KSH */
- else
- ungetsc(c2);
- return c;
-
- case '>':
- case '<': {
- register struct ioword *iop;
-
- iop = (struct ioword *) alloc(sizeof(*iop), ATEMP);
- iop->unit = c2/*unit*/;
-
- c2 = getsc();
- /* <<, >>, <> are ok, >< is not */
- if (c == c2 || (c == '<' && c2 == '>')) {
- iop->flag = c == c2 ?
- (c == '>' ? IOCAT : IOHERE) : IORDWR;
- if (iop->flag == IOHERE)
- if ((c2 = getsc()) == '-')
- iop->flag |= IOSKIP;
- else
- ungetsc(c2);
- } else if (c2 == '&')
- iop->flag = IODUP | (c == '<' ? IORDUP : 0);
- else {
- iop->flag = c == '>' ? IOWRITE : IOREAD;
- if (c == '>' && c2 == '|')
- iop->flag |= IOCLOB;
- else
- ungetsc(c2);
- }
-
- iop->name = (char *) 0;
- iop->delim = (char *) 0;
- yylval.iop = iop;
- return REDIR;
- }
- case '\n':
- gethere();
- if (cf & CONTIN)
- goto Again;
- return c;
-
- case '(': /*)*/
-#ifdef KSH
- if (!Flag(FSH)) {
- if ((c2 = getsc()) == '(') /*)*/
- c = MDPAREN;
- else
- ungetsc(c2);
- }
-#endif /* KSH */
- return c;
- /*(*/
- case ')':
- return c;
- }
- }
-
- *wp++ = EOS; /* terminate word */
- yylval.cp = Xclose(ws, wp);
- if (state == SWORD
-#ifdef KSH
- || state == SDPAREN
-#endif /* KSH */
- ) /* ONEWORD? */
- return LWORD;
- ungetsc(c); /* unget terminator */
-
- /* copy word to unprefixed string ident */
- for (sp = yylval.cp, dp = ident; dp < ident+IDENT && (c = *sp++) == CHAR; )
- *dp++ = *sp++;
- /* Make sure the ident array stays '\0' paded */
- memset(dp, 0, (ident+IDENT) - dp + 1);
- if (c != EOS)
- *ident = '\0'; /* word is not unquoted */
-
- if (*ident != '\0' && (cf&(KEYWORD|ALIAS))) {
- struct tbl *p;
- int h = hash(ident);
-
- /* { */
- if ((cf & KEYWORD) && (p = tsearch(&keywords, ident, h))
- && (!(cf & ESACONLY) || p->val.i == ESAC || p->val.i == '}'))
- {
- afree(yylval.cp, ATEMP);
- return p->val.i;
- }
- if ((cf & ALIAS) && (p = tsearch(&aliases, ident, h))
- && (p->flag & ISSET))
- {
- register Source *s;
-
- for (s = source; s->type == SALIAS; s = s->next)
- if (s->u.tblp == p)
- return LWORD;
- /* push alias expansion */
- s = pushs(SALIAS, source->areap);
- s->start = s->str = p->val.s;
- s->u.tblp = p;
- s->next = source;
- source = s;
- afree(yylval.cp, ATEMP);
- goto Again;
- }
- }
-
- return LWORD;
-}
-
-static void
-gethere()
-{
- register struct ioword **p;
-
- for (p = heres; p < herep; p++)
- readhere(*p);
- herep = heres;
-}
-
-/*
- * read "<<word" text into temp file
- */
-
-static void
-readhere(iop)
- register struct ioword *iop;
-{
- struct shf *volatile shf;
- struct temp *h;
- register int c;
- char *volatile eof;
- char *eofp;
- int skiptabs;
- int i;
-
- eof = evalstr(iop->delim, 0);
-
- if (e->flags & EF_FUNC_PARSE) {
- h = maketemp(APERM);
- h->next = func_heredocs;
- func_heredocs = h;
- } else {
- h = maketemp(ATEMP);
- h->next = e->temps;
- e->temps = h;
- }
- iop->name = h->name;
- if (!(shf = h->shf))
- yyerror("cannot create temporary file %s - %s\n",
- h->name, strerror(errno));
-
- newenv(E_ERRH);
- i = ksh_sigsetjmp(e->jbuf, 0);
- if (i) {
- quitenv();
- shf_close(shf);
- unwind(i);
- }
-
- if (!(iop->flag & IOEVAL))
- ignore_backslash_newline++;
-
- for (;;) {
- eofp = eof;
- skiptabs = iop->flag & IOSKIP;
- while ((c = getsc()) != 0) {
- if (skiptabs) {
- if (c == '\t')
- continue;
- skiptabs = 0;
- }
- if (c != *eofp)
- break;
- eofp++;
- }
- /* Allow EOF here so commands with out trailing newlines
- * will work (eg, ksh -c '...', $(...), etc).
- */
- if (*eofp == '\0' && (c == 0 || c == '\n'))
- break;
- ungetsc(c);
- shf_write(eof, eofp - eof, shf);
- while ((c = getsc()) != '\n') {
- if (c == 0)
- yyerror("here document `%s' unclosed\n", eof);
- shf_putc(c, shf);
- }
- shf_putc(c, shf);
- }
- shf_flush(shf);
- if (shf_error(shf))
- yyerror("error saving here document `%s': %s\n",
- eof, strerror(shf_errno(shf)));
- /*XXX add similar checks for write errors everywhere */
- quitenv();
- shf_close(shf);
- if (!(iop->flag & IOEVAL))
- ignore_backslash_newline--;
-}
-
-void
-#ifdef HAVE_PROTOTYPES
-yyerror(const char *fmt, ...)
-#else
-yyerror(fmt, va_alist)
- const char *fmt;
- va_dcl
-#endif
-{
- va_list va;
-
- yynerrs++;
- /* pop aliases and re-reads */
- while (source->type == SALIAS || source->type == SREREAD)
- source = source->next;
- source->str = null; /* zap pending input */
-
- error_prefix(TRUE);
- SH_VA_START(va, fmt);
- shf_vfprintf(shl_out, fmt, va);
- va_end(va);
- errorf(null);
-}
-
-/*
- * input for yylex with alias expansion
- */
-
-Source *
-pushs(type, areap)
- int type;
- Area *areap;
-{
- register Source *s;
-
- s = (Source *) alloc(sizeof(Source), areap);
- s->type = type;
- s->str = null;
- s->start = NULL;
- s->line = 0;
- s->errline = 0;
- s->file = NULL;
- s->flags = 0;
- s->next = NULL;
- s->areap = areap;
- if (type == SFILE || type == SSTDIN) {
- char *dummy;
- Xinit(s->xs, dummy, 256, s->areap);
- } else
- memset(&s->xs, 0, sizeof(s->xs));
- return s;
-}
-
-static int
-getsc__()
-{
- register Source *s = source;
- register int c;
-
- while ((c = *s->str++) == 0) {
- s->str = NULL; /* return 0 for EOF by default */
- switch (s->type) {
- case SEOF:
- s->str = null;
- return 0;
-
- case SSTDIN:
- case SFILE:
- getsc_line(s);
- break;
-
- case SWSTR:
- break;
-
- case SSTRING:
- break;
-
- case SWORDS:
- s->start = s->str = *s->u.strv++;
- s->type = SWORDSEP;
- break;
-
- case SWORDSEP:
- if (*s->u.strv == NULL) {
- s->start = s->str = newline;
- s->type = SEOF;
- } else {
- s->start = s->str = space;
- s->type = SWORDS;
- }
- break;
-
- case SALIAS:
- if (s->flags & SF_ALIASEND) {
- /* pass on an unused SF_ALIAS flag */
- source = s->next;
- source->flags |= s->flags & SF_ALIAS;
- s = source;
- } else if (*s->u.tblp->val.s
- && isspace(strchr(s->u.tblp->val.s, 0)[-1]))
- {
- source = s = s->next; /* pop source stack */
- /* Note that this alias ended with a space,
- * enabling alias expansion on the following
- * word.
- */
- s->flags |= SF_ALIAS;
- } else {
- /* At this point, we need to keep the current
- * alias in the source list so recursive
- * aliases can be detected and we also need
- * to return the next character. Do this
- * by temporarily popping the alias to get
- * the next character and then put it back
- * in the source list with the SF_ALIASEND
- * flag set.
- */
- source = s->next; /* pop source stack */
- source->flags |= s->flags & SF_ALIAS;
- c = getsc__();
- if (c) {
- s->flags |= SF_ALIASEND;
- s->ugbuf[0] = c; s->ugbuf[1] = '\0';
- s->start = s->str = s->ugbuf;
- s->next = source;
- source = s;
- } else {
- s = source;
- /* avoid reading eof twice */
- s->str = NULL;
- break;
- }
- }
- continue;
-
- case SREREAD:
- if (s->start != s->ugbuf) /* yuck */
- afree(s->u.freeme, ATEMP);
- source = s = s->next;
- continue;
- }
- if (s->str == NULL) {
- s->type = SEOF;
- s->start = s->str = null;
- return '\0';
- }
- if (s->flags & SF_ECHO) {
- shf_puts(s->str, shl_out);
- shf_flush(shl_out);
- }
- }
- return c;
-}
-
-static void
-getsc_line(s)
- Source *s;
-{
- char *xp = Xstring(s->xs, xp);
- int interactive = Flag(FTALKING) && s->type == SSTDIN;
- int have_tty = interactive && (s->flags & SF_TTY);
-
- /* Done here to ensure nothing odd happens when a timeout occurs */
- XcheckN(s->xs, xp, LINE);
- *xp = '\0';
- s->start = s->str = xp;
-
-#ifdef KSH
- if (have_tty && ksh_tmout) {
- ksh_tmout_state = TMOUT_READING;
- alarm(ksh_tmout);
- }
-#endif /* KSH */
-#ifdef EDIT
- if (have_tty && (0
-# ifdef VI
- || Flag(FVI)
-# endif /* VI */
-# ifdef EMACS
- || Flag(FEMACS) || Flag(FGMACS)
-# endif /* EMACS */
- ))
- {
- int nread;
-
- nread = x_read(xp, LINE);
- if (nread < 0) /* read error */
- nread = 0;
- xp[nread] = '\0';
- xp += nread;
- }
- else
-#endif /* EDIT */
- {
- if (interactive) {
- pprompt(prompt, 0);
-#ifdef OS2
- setmode (0, O_TEXT);
-#endif /* OS2 */
- } else
- s->line++;
-
- while (1) {
- char *p = shf_getse(xp, Xnleft(s->xs, xp), s->u.shf);
-
- if (!p && shf_error(s->u.shf)
- && shf_errno(s->u.shf) == EINTR)
- {
- shf_clearerr(s->u.shf);
- if (trap)
- runtraps(0);
- continue;
- }
- if (!p || (xp = p, xp[-1] == '\n'))
- break;
- /* double buffer size */
- xp++; /* move past null so doubling works... */
- XcheckN(s->xs, xp, Xlength(s->xs, xp));
- xp--; /* ...and move back again */
- }
-#ifdef OS2
- setmode(0, O_BINARY);
-#endif /* OS2 */
- /* flush any unwanted input so other programs/builtins
- * can read it. Not very optimal, but less error prone
- * than flushing else where, dealing with redirections,
- * etc..
- * todo: reduce size of shf buffer (~128?) if SSTDIN
- */
- if (s->type == SSTDIN)
- shf_flush(s->u.shf);
- }
- /* XXX: temporary kludge to restore source after a
- * trap may have been executed.
- */
- source = s;
-#ifdef KSH
- if (have_tty && ksh_tmout)
- {
- ksh_tmout_state = TMOUT_EXECUTING;
- alarm(0);
- }
-#endif /* KSH */
- s->start = s->str = Xstring(s->xs, xp);
- strip_nuls(Xstring(s->xs, xp), Xlength(s->xs, xp));
- /* Note: if input is all nulls, this is not eof */
- if (Xlength(s->xs, xp) == 0) { /* EOF */
- if (s->type == SFILE)
- shf_fdclose(s->u.shf);
- s->str = NULL;
- } else if (interactive) {
-#ifdef HISTORY
- char *p = Xstring(s->xs, xp);
- if (cur_prompt == PS1)
- while (*p && ctype(*p, C_IFS) && ctype(*p, C_IFSWS))
- p++;
- if (*p) {
-# ifdef EASY_HISTORY
- if (cur_prompt == PS2)
- histappend(Xstring(s->xs, xp), 1);
- else
-# endif /* EASY_HISTORY */
- {
- s->line++;
- histsave(s->line, s->str, 1);
- }
- }
-#endif /* HISTORY */
- }
- if (interactive)
- set_prompt(PS2, (Source *) 0);
-}
-
-void
-set_prompt(to, s)
- int to;
- Source *s;
-{
- cur_prompt = to;
-
- switch (to) {
- case PS1: /* command */
-#ifdef KSH
- /* Substitute ! and !! here, before substitutions are done
- * so ! in expanded variables are not expanded.
- * NOTE: this is not what at&t ksh does (it does it after
- * substitutions, POSIX doesn't say which is to be done.
- */
- {
- struct shf *shf;
- char *ps1;
- Area *saved_atemp;
-#ifdef __GNUC__
- (void)&ps1;
-#endif
- ps1 = str_val(global("PS1"));
- shf = shf_sopen((char *) 0, strlen(ps1) * 2,
- SHF_WR | SHF_DYNAMIC, (struct shf *) 0);
- while (*ps1) {
- if (*ps1 != '!' || *++ps1 == '!')
- shf_putchar(*ps1++, shf);
- else
- shf_fprintf(shf, "%d",
- s ? s->line + 1 : 0);
- }
- ps1 = shf_sclose(shf);
- saved_atemp = ATEMP;
- newenv(E_ERRH);
- if (ksh_sigsetjmp(e->jbuf, 0)) {
- prompt = safe_prompt;
- /* Don't print an error - assume it has already
- * been printed. Reason is we may have forked
- * to run a command and the child may be
- * unwinding its stack through this code as it
- * exits.
- */
- } else
- prompt = str_save(substitute(ps1, 0),
- saved_atemp);
- quitenv();
- }
-#else /* KSH */
- prompt = str_val(global("PS1"));
-#endif /* KSH */
- break;
-
- case PS2: /* command continuation */
- prompt = str_val(global("PS2"));
- break;
- }
-}
-
-/* See also related routine, promptlen() in edit.c */
-void
-pprompt(cp, ntruncate)
- const char *cp;
- int ntruncate;
-{
-#if 0
- char nbuf[32];
- int c;
-
- while (*cp != 0) {
- if (*cp != '!')
- c = *cp++;
- else if (*++cp == '!')
- c = *cp++;
- else {
- int len;
- char *p;
-
- shf_snprintf(p = nbuf, sizeof(nbuf), "%d",
- source->line + 1);
- len = strlen(nbuf);
- if (ntruncate) {
- if (ntruncate >= len) {
- ntruncate -= len;
- continue;
- }
- p += ntruncate;
- len -= ntruncate;
- ntruncate = 0;
- }
- shf_write(p, len, shl_out);
- continue;
- }
- if (ntruncate)
- --ntruncate;
- else
- shf_putc(c, shl_out);
- }
-#endif /* 0 */
- shf_puts(cp + ntruncate, shl_out);
- shf_flush(shl_out);
-}
-
-/* Read the variable part of a ${...} expression (ie, up to but not including
- * the :[-+?=#%] or close-brace.
- */
-static char *
-get_brace_var(wsp, wp)
- XString *wsp;
- char *wp;
-{
- enum parse_state {
- PS_INITIAL, PS_SAW_HASH, PS_IDENT,
- PS_NUMBER, PS_VAR1, PS_END
- }
- state;
- char c;
-
- state = PS_INITIAL;
- while (1) {
- c = getsc();
- /* State machine to figure out where the variable part ends. */
- switch (state) {
- case PS_INITIAL:
- if (c == '#') {
- state = PS_SAW_HASH;
- break;
- }
- /* fall through.. */
- case PS_SAW_HASH:
- if (letter(c))
- state = PS_IDENT;
- else if (digit(c))
- state = PS_NUMBER;
- else if (ctype(c, C_VAR1))
- state = PS_VAR1;
- else
- state = PS_END;
- break;
- case PS_IDENT:
- if (!letnum(c)) {
- state = PS_END;
- if (c == '[') {
- char *tmp, *p;
-
- if (!arraysub(&tmp))
- yyerror("missing ]\n");
- *wp++ = c;
- for (p = tmp; *p; ) {
- Xcheck(*wsp, wp);
- *wp++ = *p++;
- }
- afree(tmp, ATEMP);
- c = getsc(); /* the ] */
- }
- }
- break;
- case PS_NUMBER:
- if (!digit(c))
- state = PS_END;
- break;
- case PS_VAR1:
- state = PS_END;
- break;
- case PS_END: /* keep gcc happy */
- break;
- }
- if (state == PS_END) {
- *wp++ = '\0'; /* end of variable part */
- ungetsc(c);
- break;
- }
- Xcheck(*wsp, wp);
- *wp++ = c;
- }
- return wp;
-}
-
-/*
- * Save an array subscript - returns true if matching bracket found, false
- * if eof or newline was found.
- * (Returned string double null terminated)
- */
-static int
-arraysub(strp)
- char **strp;
-{
- XString ws;
- char *wp;
- char c;
- int depth = 1; /* we are just past the initial [ */
-
- Xinit(ws, wp, 32, ATEMP);
-
- do {
- c = getsc();
- Xcheck(ws, wp);
- *wp++ = c;
- if (c == '[')
- depth++;
- else if (c == ']')
- depth--;
- } while (depth > 0 && c && c != '\n');
-
- *wp++ = '\0';
- *strp = Xclose(ws, wp);
-
- return depth == 0 ? 1 : 0;
-}
-
-/* Unget a char: handles case when we are already at the start of the buffer */
-static const char *
-ungetsc(c)
- int c;
-{
- if (backslash_skip)
- backslash_skip--;
- /* Don't unget eof... */
- if (source->str == null && c == '\0')
- return source->str;
- if (source->str > source->start)
- source->str--;
- else {
- Source *s;
-
- s = pushs(SREREAD, source->areap);
- s->ugbuf[0] = c; s->ugbuf[1] = '\0';
- s->start = s->str = s->ugbuf;
- s->next = source;
- source = s;
- }
- return source->str;
-}
-
-
-/* Called to get a char that isn't a \newline sequence. */
-static int
-getsc_bn ARGS((void))
-{
- int c, c2;
-
- if (ignore_backslash_newline)
- return getsc_();
-
- if (backslash_skip == 1) {
- backslash_skip = 2;
- return getsc_();
- }
-
- backslash_skip = 0;
-
- while (1) {
- c = getsc_();
- if (c == '\\') {
- if ((c2 = getsc_()) == '\n')
- /* ignore the \newline; get the next char... */
- continue;
- ungetsc(c2);
- backslash_skip = 1;
- }
- return c;
- }
-}
diff --git a/bin/pdksh/lex.h b/bin/pdksh/lex.h
deleted file mode 100644
index bca6446d268..00000000000
--- a/bin/pdksh/lex.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/* $OpenBSD: lex.h,v 1.3 1996/10/13 21:32:20 downsj Exp $ */
-
-/*
- * Source input, lexer and parser
- */
-
-/* $From: lex.h,v 1.4 1994/05/31 13:34:34 michael Exp $ */
-
-#define IDENT 64
-
-typedef struct source Source;
-struct source {
- const char *str; /* input pointer */
- int type; /* input type */
- char const *start; /* start of current buffer */
- union {
- char **strv; /* string [] */
- struct shf *shf; /* shell file */
- struct tbl *tblp; /* alias (SALIAS) */
- char *freeme; /* also for SREREAD */
- } u;
- char ugbuf[2]; /* buffer for ungetsc() (SREREAD) and
- * alias (SALIAS) */
- int line; /* line number */
- int errline; /* line the error occured on (0 if not set) */
- const char *file; /* input file name */
- int flags; /* SF_* */
- Area *areap;
- XString xs; /* input buffer */
- Source *next; /* stacked source */
-};
-
-/* Source.type values */
-#define SEOF 0 /* input EOF */
-#define SFILE 1 /* file input */
-#define SSTDIN 2 /* read stdin */
-#define SSTRING 3 /* string */
-#define SWSTR 4 /* string without \n */
-#define SWORDS 5 /* string[] */
-#define SWORDSEP 6 /* string[] seperator */
-#define SALIAS 7 /* alias expansion */
-#define SREREAD 8 /* read ahead to be re-scanned */
-
-/* Source.flags values */
-#define SF_ECHO BIT(0) /* echo input to shlout */
-#define SF_ALIAS BIT(1) /* faking space at end of alias */
-#define SF_ALIASEND BIT(2) /* faking space at end of alias */
-#define SF_TTY BIT(3) /* type == SSTDIN & it is a tty */
-
-/*
- * states while lexing word
- */
-#define SBASE 0 /* outside any lexical constructs */
-#define SWORD 1 /* implicit quoting for substitute() */
-#ifdef KSH
-#define SDPAREN 2 /* inside (( )), implicit quoting */
-#endif /* KSH */
-#define SSQUOTE 3 /* inside '' */
-#define SDQUOTE 4 /* inside "" */
-#define SBRACE 5 /* inside ${} */
-#define SPAREN 6 /* inside $() */
-#define SBQUOTE 7 /* inside `` */
-#define SDDPAREN 8 /* inside $(( )) */
-#define SHEREDELIM 9 /* parsing <<,<<- delimiter */
-#define SHEREDQUOTE 10 /* parsing " in <<,<<- delimiter */
-#define SPATTERN 11 /* parsing *(...|...) pattern (*+?@!) */
-#define STBRACE 12 /* parsing ${..[#%]..} */
-
-typedef union {
- int i;
- char *cp;
- char **wp;
- struct op *o;
- struct ioword *iop;
-} YYSTYPE;
-
-/* If something is added here, add it to tokentab[] in syn.c as well */
-#define LWORD 256
-#define LOGAND 257 /* && */
-#define LOGOR 258 /* || */
-#define BREAK 259 /* ;; */
-#define IF 260
-#define THEN 261
-#define ELSE 262
-#define ELIF 263
-#define FI 264
-#define CASE 265
-#define ESAC 266
-#define FOR 267
-#define SELECT 268
-#define WHILE 269
-#define UNTIL 270
-#define DO 271
-#define DONE 272
-#define IN 273
-#define FUNCTION 274
-#define TIME 275
-#define REDIR 276
-#ifdef KSH
-#define MDPAREN 277 /* (( )) */
-#endif /* KSH */
-#define BANG 278 /* ! */
-#define DBRACKET 279 /* [[ .. ]] */
-#define COPROC 280 /* |& */
-#define YYERRCODE 300
-
-/* flags to yylex */
-#define CONTIN BIT(0) /* skip new lines to complete command */
-#define ONEWORD BIT(1) /* single word for substitute() */
-#define ALIAS BIT(2) /* recognize alias */
-#define KEYWORD BIT(3) /* recognize keywords */
-#define LETEXPR BIT(4) /* get expression inside (( )) */
-#define VARASN BIT(5) /* check for var=word */
-#define ARRAYVAR BIT(6) /* parse x[1 & 2] as one word */
-#define ESACONLY BIT(7) /* only accept esac keyword */
-#define CMDWORD BIT(8) /* parsing simple command (alias related) */
-#define HEREDELIM BIT(9) /* parsing <<,<<- delimiter */
-
-#define HERES 10 /* max << in line */
-
-EXTERN Source *source; /* yyparse/yylex source */
-EXTERN YYSTYPE yylval; /* result from yylex */
-EXTERN int yynerrs;
-EXTERN struct ioword *heres [HERES], **herep;
-EXTERN char ident [IDENT+1];
-
-#ifdef HISTORY
-# define HISTORYSIZE 128 /* size of saved history */
-
-EXTERN char **history; /* saved commands */
-EXTERN char **histptr; /* last history item */
-EXTERN int histsize; /* history size */
-#endif /* HISTORY */
diff --git a/bin/pdksh/mail.c b/bin/pdksh/mail.c
deleted file mode 100644
index 79ff7aee0f6..00000000000
--- a/bin/pdksh/mail.c
+++ /dev/null
@@ -1,198 +0,0 @@
-/* $OpenBSD: mail.c,v 1.6 1997/11/16 12:07:28 niklas Exp $ */
-
-/*
- * Mailbox checking code by Robert J. Gibson, adapted for PD ksh by
- * John R. MacMillan
- */
-
-#include "config.h"
-
-#ifdef KSH
-#include "sh.h"
-#include "ksh_stat.h"
-#include "ksh_time.h"
-
-#define MBMESSAGE "you have mail in $_"
-
-typedef struct mbox {
- struct mbox *mb_next; /* next mbox in list */
- char *mb_path; /* path to mail file */
- char *mb_msg; /* to announce arrival of new mail */
- time_t mb_mtime; /* mtime of mail file */
-} mbox_t;
-
-/*
- * $MAILPATH is a linked list of mboxes. $MAIL is a treated as a
- * special case of $MAILPATH, where the list has only one node. The
- * same list is used for both since they are exclusive.
- */
-
-static mbox_t *mplist;
-static mbox_t mbox;
-static time_t mlastchkd; /* when mail was last checked */
-
-static void munset ARGS((mbox_t *mlist)); /* free mlist and mval */
-static mbox_t * mballoc ARGS((char *p, char *m)); /* allocate a new mbox */
-static void mprintit ARGS((mbox_t *mbp));
-
-void
-mcheck()
-{
- register mbox_t *mbp;
- time_t now;
- long mailcheck;
- struct tbl *vp;
- struct stat stbuf;
-
- if (getint(global("MAILCHECK"), &mailcheck) < 0)
- return;
-
- now = time((time_t *) 0);
- if (mlastchkd == 0)
- mlastchkd = now;
- if (now - mlastchkd >= mailcheck) {
- mlastchkd = now;
-
- vp = global("MAILPATH");
- if (vp && (vp->flag & ISSET))
- mbp = mplist;
- else if ((vp = global("MAIL")) && (vp->flag & ISSET))
- mbp = &mbox;
- else
- mbp = NULL;
-
- while (mbp) {
- if (mbp->mb_path && stat(mbp->mb_path, &stbuf) == 0
- && S_ISREG(stbuf.st_mode))
- {
- if (stbuf.st_size
- && mbp->mb_mtime != stbuf.st_mtime
- && stbuf.st_atime <= stbuf.st_mtime)
- mprintit(mbp);
- mbp->mb_mtime = stbuf.st_mtime;
- } else {
- /*
- * Some mail readers remove the mail
- * file if all mail is read. If file
- * does not exist, assume this is the
- * case and set mtime to zero.
- */
- mbp->mb_mtime = 0;
- }
- mbp = mbp->mb_next;
- }
- }
-}
-
-void
-mbset(p)
- register char *p;
-{
- struct stat stbuf;
-
- if (mbox.mb_msg)
- afree((void *)mbox.mb_msg, APERM);
- mbox.mb_path = p;
- mbox.mb_msg = NULL;
- if (p && stat(p,&stbuf) == 0 && S_ISREG(stbuf.st_mode))
- mbox.mb_mtime = stbuf.st_mtime;
- else
- mbox.mb_mtime = 0;
-}
-
-void
-mpset(mptoparse)
- register char *mptoparse;
-{
- register mbox_t *mbp;
- register char *mpath, *mmsg, *mval;
- char *p;
-
- munset( mplist );
- mplist = NULL;
- mval = str_save(mptoparse, APERM);
- while (mval) {
- mpath = mval;
- if ((mval = strchr(mval, PATHSEP)) != NULL) {
- *mval = '\0', mval++;
- }
- /* POSIX/bourne-shell say file%message */
- for (p = mpath; (mmsg = strchr(p, '%')); ) {
- /* a literal percent? (POSIXism) */
- if (mmsg[-1] == '\\') {
- /* use memmove() to avoid overlap problems */
- memmove(mmsg - 1, mmsg, strlen(mmsg) + 1);
- p = mmsg + 1;
- continue;
- }
- break;
- }
- /* at&t ksh says file?message */
- if (!mmsg && !Flag(FPOSIX))
- mmsg = strchr(mpath, '?');
- if (mmsg) {
- *mmsg = '\0';
- mmsg++;
- }
- mbp = mballoc(mpath, mmsg);
- mbp->mb_next = mplist;
- mplist = mbp;
- }
-}
-
-static void
-munset(mlist)
-register mbox_t *mlist;
-{
- register mbox_t *mbp;
-
- while (mlist != NULL) {
- mbp = mlist;
- mlist = mbp->mb_next;
- if (!mlist)
- afree((void *)mbp->mb_path, APERM);
- afree((void *)mbp, APERM);
- }
-}
-
-static mbox_t *
-mballoc(p, m)
- char *p;
- char *m;
-{
- struct stat stbuf;
- register mbox_t *mbp;
-
- mbp = (mbox_t *)alloc(sizeof(mbox_t), APERM);
- mbp->mb_next = NULL;
- mbp->mb_path = p;
- mbp->mb_msg = m;
- if (stat(mbp->mb_path, &stbuf) == 0 && S_ISREG(stbuf.st_mode))
- mbp->mb_mtime = stbuf.st_mtime;
- else
- mbp->mb_mtime = 0;
- return(mbp);
-}
-
-static void
-mprintit( mbp )
-mbox_t *mbp;
-{
- struct tbl *vp;
-
-#if 0
- /*
- * I doubt this $_ overloading is bad in /bin/sh mode. Anyhow, we
- * crash as the code looks now if we do not set vp. Now, this is
- * easy to fix too, but I'd like to see what POSIX says before doing
- * a change like that.
- */
- if (!Flag(FSH))
-#endif
- setstr((vp = local("_", FALSE)), mbp->mb_path);
-
- shellf("%s\n", substitute(mbp->mb_msg ? mbp->mb_msg : MBMESSAGE, 0));
-
- unset(vp, 0);
-}
-#endif /* KSH */
diff --git a/bin/pdksh/main.c b/bin/pdksh/main.c
deleted file mode 100644
index d161fb9b3d0..00000000000
--- a/bin/pdksh/main.c
+++ /dev/null
@@ -1,820 +0,0 @@
-/* $OpenBSD: main.c,v 1.9 1997/09/12 00:32:53 deraadt Exp $ */
-
-/*
- * startup, main loop, enviroments and error handling
- */
-
-#define EXTERN /* define EXTERNs in sh.h */
-
-#include "sh.h"
-#include "ksh_stat.h"
-#include "ksh_time.h"
-
-extern char **environ;
-
-/*
- * global data
- */
-
-static void reclaim ARGS((void));
-static void remove_temps ARGS((struct temp *tp));
-static int is_restricted ARGS((char *name));
-
-/*
- * shell initialization
- */
-
-static const char initifs [] = "IFS= \t\n"; /* must be R/W */
-
-static const char initsubs [] =
- "${PS2=> } ${PS3=#? } ${PS4=+ }";
-
-static const char version_param[] =
-#ifdef KSH
- "KSH_VERSION"
-#else /* KSH */
- "SH_VERSION"
-#endif /* KSH */
- ;
-
-static const char *const initcoms [] = {
- "typeset", "-x", "SHELL", "PATH", "HOME", NULL,
- "typeset", "-r", version_param, NULL,
- "typeset", "-ri", "PPID", NULL,
- "typeset", "-i", "OPTIND=1",
-#ifdef KSH
- "MAILCHECK=600", "RANDOM", "SECONDS=0", "TMOUT=0",
-#endif /* KSH */
- NULL,
- "alias",
- /* Standard ksh aliases */
- "hash=alias -t", /* not "alias -t --": hash -r needs to work */
- "type=whence -v",
-#ifdef JOBS
- "stop=kill -STOP",
- "suspend=kill -STOP $$",
-#endif
-#ifdef KSH
- "autoload=typeset -fu",
- "functions=typeset -f",
-# ifdef HISTORY
- "history=fc -l",
-# endif /* HISTORY */
- "integer=typeset -i",
- "nohup=nohup ",
- "local=typeset",
- "r=fc -e -",
-#endif /* KSH */
-#ifdef KSH
- /* Aliases that are builtin commands in at&t */
- "login=exec login",
- "newgrp=exec newgrp",
-#endif /* KSH */
- NULL,
- /* this is what at&t ksh seems to track, with the addition of emacs */
- "alias", "-tU",
- "cat", "cc", "chmod", "cp", "date", "ed", "emacs", "grep", "ls",
- "mail", "make", "mv", "pr", "rm", "sed", "sh", "vi", "who",
- NULL,
-#ifdef EXTRA_INITCOMS
- EXTRA_INITCOMS, NULL,
-#endif /* EXTRA_INITCOMS */
- NULL
-};
-
-int
-main(argc, argv)
- int argc;
- register char **argv;
-{
- register int i;
- int argi;
- Source *s;
- struct block *l;
- int restricted;
- char **wp;
- struct env env;
- int euid;
-
-#ifdef MEM_DEBUG
- chmem_push("+c", 1);
- /*chmem_push("+cd", 1);*/
-#endif
-
-#ifdef OS2
- setmode (0, O_BINARY);
- setmode (1, O_TEXT);
-#endif
-
- /* make sure argv[] is sane */
- if (!*argv) {
- static const char *empty_argv[] = {
- "pdksh", (char *) 0
- };
-
- argv = (char **) empty_argv;
- argc = 1;
- }
- kshname = *argv;
-
- ainit(&aperm); /* initialize permanent Area */
-
- /* set up base enviroment */
- memset(&env, 0, sizeof(env));
- env.type = E_NONE;
- ainit(&env.area);
- e = &env;
- newblock(); /* set up global l->vars and l->funs */
-
- /* Do this first so output routines (eg, errorf, shellf) can work */
- initio();
-
- initvar();
-
- initctypes();
-
- inittraps();
-
-#ifdef KSH
- coproc_init();
-#endif /* KSH */
-
- /* set up variable and command dictionaries */
- tinit(&taliases, APERM, 0);
- tinit(&aliases, APERM, 0);
- tinit(&homedirs, APERM, 0);
-
- /* define shell keywords */
- initkeywords();
-
- /* define built-in commands */
- tinit(&builtins, APERM, 64); /* must be 2^n (currently 40 builtins) */
- for (i = 0; shbuiltins[i].name != NULL; i++)
- builtin(shbuiltins[i].name, shbuiltins[i].func);
- for (i = 0; kshbuiltins[i].name != NULL; i++)
- builtin(kshbuiltins[i].name, kshbuiltins[i].func);
-
- init_histvec();
-
- def_path = DEFAULT__PATH;
-#if defined(HAVE_CONFSTR) && defined(_CS_PATH)
- {
- size_t len = confstr(_CS_PATH, (char *) 0, 0);
- char *new;
-
- if (len > 0) {
- confstr(_CS_PATH, new = alloc(len + 1, APERM), len + 1);
- def_path = new;
- }
- }
-#endif /* HAVE_CONFSTR && _CS_PATH */
- path = def_path;
-
-
- /* Turn on nohup by default for how - will change to off
- * by default once people are aware of its existance
- * (at&t ksh does not have a nohup option - it always sends
- * the hup).
- */
- Flag(FNOHUP) = 1;
-
- /* Turn on brace expansion by default. At&t ksh's that have
- * alternation always have it on. BUT, posix doesn't have
- * brace expansion, so set this before setting up FPOSIX
- * (change_flag() clears FBRACEEXPAND when FPOSIX is set).
- */
-#ifdef BRACE_EXPAND
- Flag(FBRACEEXPAND) = 1;
-#endif /* BRACE_EXPAND */
-
- /* set posix flag just before environment so that it will have
- * exactly the same effect as the POSIXLY_CORRECT environment
- * variable. If this needs to be done sooner to ensure correct posix
- * operation, an initial scan of the environment will also have
- * done sooner.
- */
-#ifdef POSIXLY_CORRECT
- change_flag(FPOSIX, OF_SPECIAL, 1);
-#endif /* POSIXLY_CORRECT */
-
- /* Check to see if we're /bin/sh. */
- if (!strcmp(&kshname[strlen(kshname) - 3], "/sh")
- || !strcmp(kshname, "sh") || !strcmp(kshname, "-sh"))
- Flag(FSH) = 1;
-
- /* import enviroment */
- if (environ != NULL)
- for (wp = environ; *wp != NULL; wp++)
- typeset(*wp, IMPORT|EXPORT, 0, 0, 0);
-
- kshpid = procpid = getpid();
- typeset(initifs, 0, 0, 0, 0); /* for security */
-
- /* assign default shell variable values */
- substitute(initsubs, 0);
-
- /* Figure out the current working directory and set $PWD */
- {
- struct stat s_pwd, s_dot;
- struct tbl *pwd_v = global("PWD");
- char *pwd = str_val(pwd_v);
- char *pwdx = pwd;
-
- /* Try to use existing $PWD if it is valid */
- if (!ISABSPATH(pwd)
- || stat(pwd, &s_pwd) < 0 || stat(".", &s_dot) < 0
- || s_pwd.st_dev != s_dot.st_dev
- || s_pwd.st_ino != s_dot.st_ino)
- pwdx = (char *) 0;
- set_current_wd(pwdx);
- if (current_wd[0])
- simplify_path(current_wd);
- /* Only set pwd if we know where we are or if it had a
- * bogus value
- */
- if (current_wd[0] || pwd != null)
- setstr(pwd_v, current_wd);
- }
- setint(global("PPID"), (long) getppid());
-#ifdef KSH
- setint(global("RANDOM"), (long) time((time_t *)0));
-#endif /* KSH */
- setstr(global(version_param), ksh_version);
-
- /* execute initialization statements */
- for (wp = (char**) initcoms; *wp != NULL; wp++) {
- shcomexec(wp);
- for (; *wp != NULL; wp++)
- ;
- }
-
- euid = geteuid();
- safe_prompt = euid ? "$ " : "# ";
- {
- struct tbl *vp = global("PS1");
-
- /* Set PS1 if it isn't set, or we are root and prompt doesn't
- * contain a #.
- */
- if (!(vp->flag & ISSET) || (!euid && !strchr(str_val(vp), '#')))
- setstr(vp, safe_prompt);
- }
-
- /* Set this before parsing arguments */
- Flag(FPRIVILEGED) = getuid() != euid || getgid() != getegid();
-
- /* this to note if monitor is set on command line (see below) */
- Flag(FMONITOR) = 127;
- argi = parse_args(argv, OF_CMDLINE, (int *) 0);
- if (argi < 0)
- exit(1);
-
- if (Flag(FCOMMAND)) {
- s = pushs(SSTRING, ATEMP);
- if (!(s->start = s->str = argv[argi++]))
- errorf("-c requires an argument");
- if (argv[argi])
- kshname = argv[argi++];
- } else if (argi < argc && !Flag(FSTDIN)) {
- s = pushs(SFILE, ATEMP);
-#ifdef OS2
- /* a bug in os2 extproc shell processing doesn't
- * pass full pathnames so we have to search for it.
- * This changes the behavior of 'ksh arg' to search
- * the users search path but it can't be helped.
- */
- s->file = search(argv[argi++], path, R_OK, (int *) 0);
- if (!s->file || !*s->file)
- s->file = argv[argi - 1];
-#else
- s->file = argv[argi++];
-#endif /* OS2 */
- s->u.shf = shf_open(s->file, O_RDONLY, 0, SHF_MAPHI|SHF_CLEXEC);
- if (s->u.shf == NULL) {
- exstat = 127; /* POSIX */
- errorf("%s: %s", s->file, strerror(errno));
- }
- kshname = s->file;
- } else {
- Flag(FSTDIN) = 1;
- s = pushs(SSTDIN, ATEMP);
- s->file = "<stdin>";
- s->u.shf = shf_fdopen(0, SHF_RD | can_seek(0),
- (struct shf *) 0);
- if (isatty(0) && isatty(2)) {
- Flag(FTALKING) = 1;
- /* The following only if isatty(0) */
- s->flags |= SF_TTY;
- s->u.shf->flags |= SHF_INTERRUPT;
- s->file = (char *) 0;
- }
- }
-
- /* This bizarreness is mandated by POSIX */
- {
- struct stat s_stdin;
-
- if (fstat(0, &s_stdin) >= 0 && S_ISCHR(s_stdin.st_mode))
- reset_nonblock(0);
- }
-
- /* initialize job control */
- i = Flag(FMONITOR) != 127;
- Flag(FMONITOR) = 0;
- j_init(i);
-#ifdef EDIT
- /* Do this after j_init(), as tty_fd is not initialized 'til then */
- if (Flag(FTALKING))
- x_init();
-#endif
-
- l = e->loc;
- l->argv = &argv[argi - 1];
- l->argc = argc - argi;
- l->argv[0] = (char *) kshname;
- getopts_reset(1);
-
- /* Disable during .profile/ENV reading */
- restricted = Flag(FRESTRICTED);
- Flag(FRESTRICTED) = 0;
-
- /* Do this before profile/$ENV so that if it causes problems in them,
- * user will know why things broke.
- */
- if (!current_wd[0] && Flag(FTALKING))
- warningf(FALSE, "Cannot determine current working directory");
-
- if (Flag(FLOGIN)) {
-#ifdef OS2
- char *profile;
-
- /* Try to find a profile - first see if $INIT has a value,
- * then try /etc/profile.ksh, then c:/usr/etc/profile.ksh.
- */
- if (!Flag(FPRIVILEGED)
- && strcmp(profile = substitute("$INIT/profile.ksh", 0),
- "/profile.ksh"))
- include(profile, 0, (char **) 0, 1);
- else if (include("/etc/profile.ksh", 0, (char **) 0, 1) < 0)
- include("c:/usr/etc/profile.ksh", 0, (char **) 0, 1);
- if (!Flag(FPRIVILEGED))
- include(substitute("$HOME/profile.ksh", 0), 0,
- (char **) 0, 1);
-#else /* OS2 */
- include(KSH_SYSTEM_PROFILE, 0, (char **) 0, 1);
- if (!Flag(FPRIVILEGED))
- include(substitute("$HOME/.profile", 0), 0,
- (char **) 0, 1);
-#endif /* OS2 */
- }
-
- if (Flag(FPRIVILEGED))
- include("/etc/suid_profile", 0, (char **) 0, 1);
- else {
- char *env_file;
-
-#ifndef KSH
- if (!Flag(FPOSIX))
- env_file = null;
- else
-#endif /* !KSH */
- /* include $ENV */
- env_file = str_val(global("ENV"));
-
-#ifdef DEFAULT_ENV
- /* If env isn't set, include default environment */
- if (env_file == null)
- env_file = DEFAULT_ENV;
-#endif /* DEFAULT_ENV */
- env_file = substitute(env_file, DOTILDE);
- if (*env_file != '\0')
- include(env_file, 0, (char **) 0, 1);
-#ifdef OS2
- else if (Flag(FTALKING))
- include(substitute("$HOME/kshrc.ksh", 0), 0,
- (char **) 0, 1);
-#endif /* OS2 */
- }
-
- if (is_restricted(argv[0]) || is_restricted(str_val(global("SHELL"))))
- restricted = 1;
- if (restricted) {
- static const char *const restr_com[] = {
- "typeset", "-r", "PATH",
- "ENV", "SHELL",
- (char *) 0
- };
- shcomexec((char **) restr_com);
- /* After typeset command... */
- Flag(FRESTRICTED) = 1;
- }
-
- if (Flag(FTALKING)) {
- hist_init(s);
-#ifdef KSH
- alarm_init();
-#endif /* KSH */
- } else
- Flag(FTRACKALL) = 1; /* set after ENV */
-
- shell(s, TRUE); /* doesn't return */
- return 0;
-}
-
-int
-include(name, argc, argv, intr_ok)
- const char *name;
- int argc;
- char **argv;
- int intr_ok;
-{
- register Source *volatile s = NULL;
- Source *volatile sold;
- struct shf *shf;
- char **volatile old_argv;
- volatile int old_argc;
- int i;
-
- shf = shf_open(name, O_RDONLY, 0, SHF_MAPHI|SHF_CLEXEC);
- if (shf == NULL)
- return -1;
-
- if (argv) {
- old_argv = e->loc->argv;
- old_argc = e->loc->argc;
- } else {
- old_argv = (char **) 0;
- old_argc = 0;
- }
- sold = source;
- newenv(E_INCL);
- i = ksh_sigsetjmp(e->jbuf, 0);
- if (i) {
- quitenv();
- source = sold;
- if (s)
- shf_close(s->u.shf);
- if (old_argv) {
- e->loc->argv = old_argv;
- e->loc->argc = old_argc;
- }
- switch (i) {
- case LRETURN:
- case LERROR:
- return exstat & 0xff; /* see below */
- case LINTR:
- /* intr_ok is set if we are including .profile or $ENV.
- * If user ^C's out, we don't want to kill the shell...
- */
- if (intr_ok && (exstat - 128) != SIGTERM)
- return 1;
- /* fall through... */
- case LEXIT:
- case LLEAVE:
- case LSHELL:
- unwind(i);
- /*NOREACHED*/
- default:
- internal_errorf(1, "include: %d", i);
- /*NOREACHED*/
- }
- }
- if (argv) {
- e->loc->argv = argv;
- e->loc->argc = argc;
- }
- s = pushs(SFILE, ATEMP);
- s->u.shf = shf;
- s->file = str_save(name, ATEMP);
- i = shell(s, FALSE);
- source = sold;
- shf_close(s->u.shf);
- quitenv();
- if (old_argv) {
- e->loc->argv = old_argv;
- e->loc->argc = old_argc;
- }
- return i & 0xff; /* & 0xff to ensure value not -1 */
-}
-
-int
-command(comm)
- const char *comm;
-{
- register Source *s;
-
- s = pushs(SSTRING, ATEMP);
- s->start = s->str = comm;
- return shell(s, FALSE);
-}
-
-/*
- * run the commands from the input source, returning status.
- */
-int
-shell(s, toplevel)
- Source *volatile s; /* input source */
- int volatile toplevel;
-{
- struct op *t;
- volatile int wastty = s->flags & SF_TTY;
- volatile int attempts = 13;
- volatile int interactive = Flag(FTALKING) && toplevel;
- int i;
-
- newenv(E_PARSE);
- if (interactive)
- really_exit = 0;
- i = ksh_sigsetjmp(e->jbuf, 0);
- if (i) {
- s->start = s->str = null;
- switch (i) {
- case LINTR: /* we get here if SIGINT not caught or ignored */
- case LERROR:
- case LSHELL:
- if (interactive) {
- if (i == LINTR)
- shellf(newline);
- /* Reset any eof that was read as part of a
- * multiline command.
- */
- if (Flag(FIGNOREEOF) && s->type == SEOF
- && wastty)
- s->type = SSTDIN;
- /* Used by exit command to get back to
- * top level shell. Kind of strange since
- * interactive is set if we are reading from
- * a tty, but to have stopped jobs, one only
- * needs FMONITOR set (not FTALKING/SF_TTY)...
- */
- break;
- }
- /* fall through... */
- case LEXIT:
- case LLEAVE:
- case LRETURN:
- quitenv();
- unwind(i); /* keep on going */
- /*NOREACHED*/
- default:
- quitenv();
- internal_errorf(1, "shell: %d", i);
- /*NOREACHED*/
- }
- }
-
- while (1) {
- if (trap)
- runtraps(0);
-
- if (s->next == NULL)
- if (Flag(FVERBOSE))
- s->flags |= SF_ECHO;
- else
- s->flags &= ~SF_ECHO;
-
- if (interactive) {
- j_notify();
-#ifdef KSH
- mcheck();
-#endif /* KSH */
- set_prompt(PS1, s);
- }
-
- t = compile(s);
- if (t != NULL && t->type == TEOF) {
- if (wastty && Flag(FIGNOREEOF) && --attempts > 0) {
- shellf("Use `exit' to leave ksh\n");
- s->type = SSTDIN;
- } else if (wastty && !really_exit
- && j_stopped_running())
- {
- really_exit = 1;
- s->type = SSTDIN;
- } else {
- /* this for POSIX, which says EXIT traps
- * shall be taken in the environment
- * immediately after the last command
- * executed.
- */
- if (toplevel)
- unwind(LEXIT);
- break;
- }
- }
-
- if (t && (!Flag(FNOEXEC) || (s->flags & SF_TTY)))
- exstat = execute(t, 0);
-
- if (t != NULL && t->type != TEOF && interactive && really_exit)
- really_exit = 0;
-
- reclaim();
- }
- quitenv();
- return exstat;
-}
-
-/* return to closest error handler or shell(), exit if none found */
-void
-unwind(i)
- int i;
-{
- /* ordering for EXIT vs ERR is a bit odd (this is what at&t ksh does) */
- if (i == LEXIT || (Flag(FERREXIT) && (i == LERROR || i == LINTR)
- && sigtraps[SIGEXIT_].trap))
- {
- runtrap(&sigtraps[SIGEXIT_]);
- i = LLEAVE;
- } else if (Flag(FERREXIT) && (i == LERROR || i == LINTR)) {
- runtrap(&sigtraps[SIGERR_]);
- i = LLEAVE;
- }
- while (1) {
- switch (e->type) {
- case E_PARSE:
- case E_FUNC:
- case E_INCL:
- case E_LOOP:
- case E_ERRH:
- ksh_siglongjmp(e->jbuf, i);
- /*NOTREACHED*/
-
- case E_NONE: /* bottom of the stack */
- {
- if (Flag(FTALKING))
- hist_finish();
- j_exit();
- remove_temps(func_heredocs);
- if (i == LINTR) {
- int sig = exstat - 128;
-
- /* ham up our death a bit (at&t ksh
- * only seems to do this for SIGTERM)
- * Don't do it for SIGQUIT, since we'd
- * dump a core..
- */
- if (sig == SIGINT || sig == SIGTERM) {
- setsig(&sigtraps[sig], SIG_DFL,
- SS_RESTORE_CURR|SS_FORCE);
- kill(0, sig);
- }
- }
- exit(exstat);
- /* NOTREACHED */
- }
-
- default:
- quitenv();
- }
- }
-}
-
-void
-newenv(type)
- int type;
-{
- register struct env *ep;
-
- ep = (struct env *) alloc(sizeof(*ep), ATEMP);
- ep->type = type;
- ep->flags = 0;
- ainit(&ep->area);
- ep->loc = e->loc;
- ep->savefd = NULL;
- ep->oenv = e;
- ep->temps = NULL;
- e = ep;
-}
-
-void
-quitenv()
-{
- register struct env *ep = e;
- register int fd;
-
- if (ep->oenv == NULL) /* cleanup_parents_env() was called */
- exit(exstat); /* exit child */
- if (ep->oenv->loc != ep->loc)
- popblock();
- if (ep->savefd != NULL) {
- for (fd = 0; fd < NUFILE; fd++)
- /* if ep->savefd[fd] < 0, means fd was closed */
- if (ep->savefd[fd])
- restfd(fd, ep->savefd[fd]);
- if (ep->savefd[2]) /* Clear any write errors */
- shf_reopen(2, SHF_WR, shl_out);
- }
- reclaim();
- e = e->oenv;
- afree(ep, ATEMP);
-}
-
-/* Called after a fork to cleanup stuff left over from parents environment */
-void
-cleanup_parents_env()
-{
- struct env *ep;
- int fd;
-
- /* Don't clean up temporary files - parent will probably need them.
- * Also, can't easily reclaim memory since variables, etc. could be
- * anywyere.
- */
-
- /* close all file descriptors hiding in savefd */
- for (ep = e; ep; ep = ep->oenv) {
- if (ep->savefd)
- for (fd = 0; fd < NUFILE; fd++)
- if (ep->savefd[fd] > 0)
- close(ep->savefd[fd]);
- }
- e->oenv = (struct env *) 0;
-}
-
-/* Called just before an execve cleanup stuff temporary files */
-void
-cleanup_proc_env()
-{
- struct env *ep;
-
- for (ep = e; ep; ep = ep->oenv)
- remove_temps(ep->temps);
- remove_temps(func_heredocs);
-}
-
-/* remove temp files and free ATEMP Area */
-static void
-reclaim()
-{
- remove_temps(e->temps);
- e->temps = NULL;
- afreeall(&e->area);
-}
-
-static void
-remove_temps(tp)
- struct temp *tp;
-{
-#ifdef OS2
- static struct temp *delayed_remove;
- struct temp *t, **tprev;
-
- if (delayed_remove) {
- for (tprev = &delayed_remove, t = delayed_remove; t; t = *tprev)
- /* No need to check t->pid here... */
- if (unlink(t->name) >= 0 || errno == ENOENT) {
- *tprev = t->next;
- afree(t, APERM);
- } else
- tprev = &t->next;
- }
-#endif /* OS2 */
-
- for (; tp != NULL; tp = tp->next)
- if (tp->pid == procpid) {
-#ifdef OS2
- /* OS/2 (and dos) do not allow files that are currently
- * open to be removed, so we cache it away for future
- * removal.
- * XXX should only do this if errno
- * is Efile-still-open-can't-remove
- * (but I don't know what that is...)
- */
- if (unlink(tp->name) < 0 && errno != ENOENT) {
- t = (struct temp *) alloc(
- sizeof(struct temp) + strlen(tp->name) + 1,
- APERM);
- memset(t, 0, sizeof(struct temp));
- strcpy(t->name, tp->name);
- t->next = delayed_remove;
- delayed_remove = t;
- }
-#else /* OS2 */
- unlink(tp->name);
-#endif /* OS2 */
- }
-}
-
-/* Returns true if name refers to a restricted shell */
-static int
-is_restricted(name)
- char *name;
-{
- char *p;
-
- if ((p = ksh_strrchr_dirsep(name)))
- name = p;
- /* accepts rsh, rksh, rpdksh, pdrksh, etc. */
- return (p = strchr(name, 'r')) && strstr(p, "sh");
-}
-
-void
-aerror(ap, msg)
- Area *ap;
- const char *msg;
-{
- internal_errorf(1, "alloc: %s", msg);
- errorf(null); /* this is never executed - keeps gcc quiet */
- /*NOTREACHED*/
-}
diff --git a/bin/pdksh/misc.c b/bin/pdksh/misc.c
deleted file mode 100644
index 5287f4e9dfa..00000000000
--- a/bin/pdksh/misc.c
+++ /dev/null
@@ -1,1318 +0,0 @@
-/* $OpenBSD: misc.c,v 1.6 1997/06/19 13:58:45 kstailey Exp $ */
-
-/*
- * Miscellaneous functions
- */
-
-#include "sh.h"
-#include <ctype.h> /* for FILECHCONV */
-#ifdef HAVE_LIMITS_H
-# include <limits.h>
-#endif
-
-#ifndef UCHAR_MAX
-# define UCHAR_MAX 0xFF
-#endif
-
-short ctypes [UCHAR_MAX+1]; /* type bits for unsigned char */
-
-static int do_gmatch ARGS((const unsigned char *s, const unsigned char *p,
- const unsigned char *se, const unsigned char *pe,
- int isfile));
-static const unsigned char *cclass ARGS((const unsigned char *p, int sub));
-
-/*
- * Fast character classes
- */
-void
-setctypes(s, t)
- register const char *s;
- register int t;
-{
- register int i;
-
- if (t & C_IFS) {
- for (i = 0; i < UCHAR_MAX+1; i++)
- ctypes[i] &= ~C_IFS;
- ctypes[0] |= C_IFS; /* include \0 in C_IFS */
- }
- while (*s != 0)
- ctypes[(unsigned char) *s++] |= t;
-}
-
-void
-initctypes()
-{
- register int c;
-
- for (c = 'a'; c <= 'z'; c++)
- ctypes[c] |= C_ALPHA;
- for (c = 'A'; c <= 'Z'; c++)
- ctypes[c] |= C_ALPHA;
- ctypes['_'] |= C_ALPHA;
- setctypes("0123456789", C_DIGIT);
- setctypes(" \t\n|&;<>()", C_LEX1); /* \0 added automatically */
- setctypes("*@#!$-?", C_VAR1);
- setctypes(" \t\n", C_IFSWS);
- setctypes("=-+?", C_SUBOP1);
- setctypes("#%", C_SUBOP2);
- setctypes(" \n\t\"#$&'()*;<>?[\\`|", C_QUOTE);
-}
-
-/* convert unsigned long to base N string */
-
-char *
-ulton(n, base)
- register unsigned long n;
- int base;
-{
- register char *p;
- static char buf [20];
-
- p = &buf[sizeof(buf)];
- *--p = '\0';
- do {
- *--p = "0123456789ABCDEF"[n%base];
- n /= base;
- } while (n != 0);
- return p;
-}
-
-char *
-str_save(s, ap)
- register const char *s;
- Area *ap;
-{
- return s ? strcpy((char*) alloc((size_t)strlen(s)+1, ap), s) : NULL;
-}
-
-/* Allocate a string of size n+1 and copy upto n characters from the possibly
- * null terminated string s into it. Always returns a null terminated string
- * (unless n < 0).
- */
-char *
-str_nsave(s, n, ap)
- register const char *s;
- int n;
- Area *ap;
-{
- char *ns;
-
- if (n < 0)
- return 0;
- ns = alloc(n + 1, ap);
- ns[0] = '\0';
- return strncat(ns, s, n);
-}
-
-/* called from expand.h:XcheckN() to grow buffer */
-char *
-Xcheck_grow_(xsp, xp, more)
- XString *xsp;
- char *xp;
- int more;
-{
- char *old_beg = xsp->beg;
-
- xsp->len += more > xsp->len ? more : xsp->len;
- xsp->beg = aresize(xsp->beg, xsp->len + 8, xsp->areap);
- xsp->end = xsp->beg + xsp->len;
- return xsp->beg + (xp - old_beg);
-}
-
-const struct option options[] = {
- /* Special cases (see parse_args()): -A, -o, -s.
- * Options are sorted by their longnames - the order of these
- * entries MUST match the order of sh_flag F* enumerations in sh.h.
- */
- { "allexport", 'a', OF_ANY },
-#ifdef BRACE_EXPAND
- { "braceexpand", 0, OF_ANY }, /* non-standard */
-#endif
- { "bgnice", 0, OF_ANY },
- { null, 'c', OF_CMDLINE },
-#ifdef EMACS
- { "emacs", 0, OF_ANY },
-#endif
- { "errexit", 'e', OF_ANY },
-#ifdef EMACS
- { "gmacs", 0, OF_ANY },
-#endif
- { "ignoreeof", 0, OF_ANY },
- { "interactive",'i', OF_CMDLINE },
- { "keyword", 'k', OF_ANY },
- { "login", 'l', OF_CMDLINE },
- { "markdirs", 'X', OF_ANY },
-#ifdef JOBS
- { "monitor", 'm', OF_ANY },
-#else /* JOBS */
- { null, 'm', 0 }, /* so FMONITOR not ifdef'd */
-#endif /* JOBS */
- { "noclobber", 'C', OF_ANY },
- { "noexec", 'n', OF_ANY },
- { "noglob", 'f', OF_ANY },
- { "nohup", 0, OF_ANY },
- { "nolog", 0, OF_ANY }, /* no effect */
-#ifdef JOBS
- { "notify", 'b', OF_ANY },
-#endif /* JOBS */
- { "nounset", 'u', OF_ANY },
- { "physical", 0, OF_ANY }, /* non-standard */
- { "posix", 0, OF_ANY }, /* non-standard */
- { "privileged", 'p', OF_ANY },
- { "restricted", 'r', OF_CMDLINE },
- { "sh", 0, OF_ANY }, /* non-standard */
- { "stdin", 's', OF_CMDLINE }, /* pseudo non-standard */
- { "trackall", 'h', OF_ANY },
- { "verbose", 'v', OF_ANY },
-#ifdef VI
- { "vi", 0, OF_ANY },
- { "viraw", 0, OF_ANY }, /* no effect */
- { "vi-show8", 0, OF_ANY }, /* non-standard */
- { "vi-tabcomplete", 0, OF_ANY }, /* non-standard */
- { "vi-esccomplete", 0, OF_ANY }, /* non-standard */
-#endif
- { "xtrace", 'x', OF_ANY },
- { NULL, 0, 0 }
-};
-
-/*
- * translate -o option into F* constant (also used for test -o option)
- */
-int
-option(n)
- const char *n;
-{
- int i;
-
- for (i = 0; options[i].name; i++)
- if (strcmp(options[i].name, n) == 0)
- return i;
-
- return -1;
-}
-
-struct options_info {
- int opt_width;
- struct {
- const char *name;
- int flag;
- } opts[NELEM(options)];
-};
-
-static char *options_fmt_entry ARGS((void *arg, int i, char *buf, int buflen));
-static void printoptions ARGS((int verbose));
-
-/* format a single select menu item */
-static char *
-options_fmt_entry(arg, i, buf, buflen)
- void *arg;
- int i;
- char *buf;
- int buflen;
-{
- struct options_info *oi = (struct options_info *) arg;
-
- shf_snprintf(buf, buflen, "%-*s %s",
- oi->opt_width, oi->opts[i].name,
- Flag(oi->opts[i].flag) ? "on" : "off");
- return buf;
-}
-
-static void
-printoptions(verbose)
- int verbose;
-{
- int i;
-
- if (verbose) {
- struct options_info oi;
- int n, len;
-
- /* verbose version */
- shprintf("Current option settings\n");
-
- for (i = n = oi.opt_width = 0; options[i].name; i++)
- if (options[i].name[0]) {
- len = strlen(options[i].name);
- oi.opts[n].name = options[i].name;
- oi.opts[n++].flag = i;
- if (len > oi.opt_width)
- oi.opt_width = len;
- }
- print_columns(shl_stdout, n, options_fmt_entry, &oi,
- oi.opt_width + 5);
- } else {
- /* short version ala ksh93 */
- shprintf("set");
- for (i = 0; options[i].name; i++)
- if (Flag(i) && options[i].name[0])
- shprintf(" -o %s", options[i].name);
- shprintf(newline);
- }
-}
-
-char *
-getoptions()
-{
- int i;
- char m[FNFLAGS + 1];
- register char *cp = m;
-
- for (i = 0; options[i].name; i++)
- if (options[i].c && Flag(i))
- *cp++ = options[i].c;
- *cp = 0;
- return str_save(m, ATEMP);
-}
-
-/* change a Flag(*) value; takes care of special actions */
-void
-change_flag(f, what, newval)
- enum sh_flag f; /* flag to change */
- int what; /* what is changing the flag (command line vs set) */
- int newval;
-{
- int oldval;
-
- oldval = Flag(f);
- Flag(f) = newval;
-#ifdef JOBS
- if (f == FMONITOR) {
- if (what != OF_CMDLINE && newval != oldval)
- j_change();
- } else
-#endif /* JOBS */
-#ifdef EDIT
- if (0
-# ifdef VI
- || f == FVI
-# endif /* VI */
-# ifdef EMACS
- || f == FEMACS || f == FGMACS
-# endif /* EMACS */
- )
- {
- if (newval) {
-# ifdef VI
- Flag(FVI) = 0;
-# endif /* VI */
-# ifdef EMACS
- Flag(FEMACS) = Flag(FGMACS) = 0;
-# endif /* EMACS */
- Flag(f) = newval;
- }
- } else
-#endif /* EDIT */
- /* Turning off -p? */
- if (f == FPRIVILEGED && oldval && !newval) {
-#ifdef OS2
- ;
-#else /* OS2 */
- seteuid(getuid());
- setuid(getuid());
- setegid(getgid());
- setgid(getgid());
-#endif /* OS2 */
- } else if (f == FPOSIX && newval) {
-#ifdef BRACE_EXPAND
- Flag(FBRACEEXPAND) = 0
-#endif /* BRACE_EXPAND */
- ;
- }
-}
-
-/* parse command line & set command arguments. returns the index of
- * non-option arguments, -1 if there is an error.
- */
-int
-parse_args(argv, what, setargsp)
- char **argv;
- int what; /* OF_CMDLINE or OF_SET */
- int *setargsp;
-{
- static char cmd_opts[NELEM(options) + 3]; /* o:\0 */
- static char set_opts[NELEM(options) + 5]; /* Ao;s\0 */
- char *opts;
- char *array;
- Getopt go;
- int i, optc, set, sortargs = 0, arrayset = 0;
-
- /* First call? Build option strings... */
- if (cmd_opts[0] == '\0') {
- char *p;
-
- /* c is also in options[], but it needs a trailing : */
- strcpy(cmd_opts, "o:"); /* see cmd_opts[] declaration */
- p = cmd_opts + strlen(cmd_opts);
- for (i = 0; options[i].name; i++)
- if (options[i].c && (options[i].flags & OF_CMDLINE))
- *p++ = options[i].c;
- *p = '\0';
-
- strcpy(set_opts, "Ao;s"); /* see set_opts[] declaration */
- p = set_opts + strlen(set_opts);
- for (i = 0; options[i].name; i++)
- if (options[i].c && (options[i].flags & OF_SET))
- *p++ = options[i].c;
- *p = '\0';
- }
-
- if (what == OF_CMDLINE) {
- char *p;
- /* Set FLOGIN before parsing options so user can clear
- * flag using +l.
- */
- Flag(FLOGIN) = (argv[0][0] == '-'
- || ((p = ksh_strrchr_dirsep(argv[0]))
- && *++p == '-'));
- opts = cmd_opts;
- } else
- opts = set_opts;
- ksh_getopt_reset(&go, GF_ERROR|GF_PLUSOPT);
- while ((optc = ksh_getopt(argv, &go, opts)) != EOF) {
- set = (go.info & GI_PLUS) ? 0 : 1;
- switch (optc) {
- case 'A':
- arrayset = set ? 1 : -1;
- break;
-
- case 'o':
- if (go.optarg == (char *) 0) {
- /* lone -o: print options
- *
- * Note that on the command line, -o requires
- * an option (ie, can't get here if what is
- * OF_CMDLINE).
- */
- printoptions(set);
- break;
- }
- i = option(go.optarg);
- if (i >= 0 && set == Flag(i))
- /* Don't check the context if the flag
- * isn't changing - makes "set -o interactive"
- * work if you're already interactive. Needed
- * if the output of "set +o" is to be used.
- */
- ;
- else if (i >= 0 && (options[i].flags & what))
- change_flag((enum sh_flag) i, what, set);
- else {
- bi_errorf("%s: bad option", go.optarg);
- return -1;
- }
- break;
-
- case '?':
- return -1;
-
- default:
- /* -s: sort positional params (at&t ksh stupidity) */
- if (what == OF_SET && optc == 's') {
- sortargs = 1;
- break;
- }
- for (i = 0; options[i].name; i++)
- if (optc == options[i].c
- && (what & options[i].flags))
- {
- change_flag((enum sh_flag) i, what,
- set);
- break;
- }
- if (!options[i].name) {
- internal_errorf(1, "parse_args: `%c'", optc);
- return -1; /* not reached */
- }
- }
- }
- if (!(go.info & GI_MINUSMINUS) && argv[go.optind]
- && (argv[go.optind][0] == '-' || argv[go.optind][0] == '+')
- && argv[go.optind][1] == '\0')
- {
- /* lone - clears -v and -x flags */
- if (argv[go.optind][0] == '-' && !Flag(FPOSIX))
- Flag(FVERBOSE) = Flag(FXTRACE) = 0;
- /* set skips lone - or + option */
- go.optind++;
- }
- if (setargsp)
- /* -- means set $#/$* even if there are no arguments */
- *setargsp = !arrayset && ((go.info & GI_MINUSMINUS)
- || argv[go.optind]);
-
- if (arrayset) {
- array = argv[go.optind++];
- if (!array) {
- bi_errorf("-A: missing array name");
- return -1;
- }
- if (!*array || *skip_varname(array, FALSE)) {
- bi_errorf("%s: is not an identifier", array);
- return -1;
- }
- } else
- array = (char *) 0; /* keep gcc happy */
- if (sortargs) {
- for (i = go.optind; argv[i]; i++)
- ;
- qsortp((void **) &argv[go.optind], (size_t) (i - go.optind),
- xstrcmp);
- }
- if (arrayset) {
- set_array(array, arrayset, argv + go.optind);
- for (; argv[go.optind]; go.optind++)
- ;
- }
-
- return go.optind;
-}
-
-/* parse a decimal number: returns 0 if string isn't a number, 1 otherwise */
-int
-getn(as, ai)
- const char *as;
- int *ai;
-{
- const char *s;
- register int n;
- int sawdigit = 0;
-
- s = as;
- if (*s == '-' || *s == '+')
- s++;
- for (n = 0; digit(*s); s++, sawdigit = 1)
- n = n * 10 + (*s - '0');
- *ai = (*as == '-') ? -n : n;
- if (*s || !sawdigit)
- return 0;
- return 1;
-}
-
-/* getn() that prints error */
-int
-bi_getn(as, ai)
- const char *as;
- int *ai;
-{
- int rv = getn(as, ai);
-
- if (!rv)
- bi_errorf("%s: bad number", as);
- return rv;
-}
-
-/* -------- gmatch.c -------- */
-
-/*
- * int gmatch(string, pattern)
- * char *string, *pattern;
- *
- * Match a pattern as in sh(1).
- * pattern character are prefixed with MAGIC by expand.
- */
-
-int
-gmatch(s, p, isfile)
- const char *s, *p;
- int isfile;
-{
- const char *se, *pe;
-
- if (s == NULL || p == NULL)
- return 0;
- se = s + strlen(s);
- pe = p + strlen(p);
- /* isfile is false iff no syntax check has been done on
- * the pattern. If check fails, just to a strcmp().
- */
- if (!isfile && !has_globbing(p, pe)) {
- int len = pe - p + 1;
- char tbuf[64];
- char *t = len <= sizeof(tbuf) ? tbuf
- : (char *) alloc(len, ATEMP);
- debunk(t, p);
- return !strcmp(t, s);
- }
- return do_gmatch((const unsigned char *) s, (const unsigned char *) se,
- (const unsigned char *) p, (const unsigned char *) pe,
- isfile);
-}
-
-/* Returns if p is a syntacticly correct globbing pattern, false
- * if it contains no pattern characters or if there is a syntax error.
- * Syntax errors are:
- * - [ with no closing ]
- * - imballenced $(...) expression
- * - [...] and *(...) not nested (eg, [a$(b|]c), *(a[b|c]d))
- */
-/*XXX
-- if no magic,
- if dest given, copy to dst
- return ?
-- if magic && (no globbing || syntax error)
- debunk to dst
- return ?
-- return ?
-*/
-int
-has_globbing(xp, xpe)
- const char *xp, *xpe;
-{
- const unsigned char *p = (const unsigned char *) xp;
- const unsigned char *pe = (const unsigned char *) xpe;
- int c;
- int nest = 0, bnest = 0;
- int saw_glob = 0;
- int in_bracket = 0; /* inside [...] */
-
- for (; p < pe; p++) {
- if (!ISMAGIC(*p))
- continue;
- if ((c = *++p) == '*' || c == '?')
- saw_glob = 1;
- else if (c == '[') {
- if (!in_bracket) {
- saw_glob = 1;
- in_bracket = 1;
- if (ISMAGIC(p[1]) && p[2] == NOT)
- p += 2;
- if (ISMAGIC(p[1]) && p[2] == ']')
- p += 2;
- }
- /* XXX Do we need to check ranges here? POSIX Q */
- } else if (c == ']') {
- if (in_bracket) {
- if (bnest) /* [a*(b]) */
- return 0;
- in_bracket = 0;
- }
- } else if ((c & 0x80) && strchr("*+?@!", c & 0x7f)) {
- saw_glob = 1;
- if (in_bracket)
- bnest++;
- else
- nest++;
- } else if (c == '|') {
- if (in_bracket && !bnest) /* *(a[foo|bar]) */
- return 0;
- } else if (c == /*(*/ ')') {
- if (in_bracket) {
- if (!bnest--) /* *(a[b)c] */
- return 0;
- } else if (nest)
- nest--;
- }
- /* else must be a MAGIC-MAGIC, or MAGIC-!, MAGIC--, MAGIC-]
- MAGIC-{, MAGIC-,, MAGIC-} */
- }
- return saw_glob && !in_bracket && !nest;
-}
-
-/* Function must return either 0 or 1 (assumed by code for 0x80|'!') */
-static int
-do_gmatch(s, se, p, pe, isfile)
- const unsigned char *s, *p;
- const unsigned char *se, *pe;
- int isfile;
-{
- register int sc, pc;
- const unsigned char *prest, *psub, *pnext;
- const unsigned char *srest;
-
- if (s == NULL || p == NULL)
- return 0;
- while (p < pe) {
- pc = *p++;
- sc = s < se ? *s : '\0';
- s++;
- if (isfile) {
- sc = FILECHCONV(sc);
- pc = FILECHCONV(pc);
- }
- if (!ISMAGIC(pc)) {
- if (sc != pc)
- return 0;
- continue;
- }
- switch (*p++) {
- case '[':
- if (sc == 0 || (p = cclass(p, sc)) == NULL)
- return 0;
- break;
-
- case '?':
- if (sc == 0)
- return 0;
- break;
-
- case '*':
- if (p == pe)
- return 1;
- s--;
- do {
- if (do_gmatch(s, se, p, pe, isfile))
- return 1;
- } while (s++ < se);
- return 0;
-
-#ifdef KSH
- /* [*+?@!](pattern|pattern|..) */
- case 0x80|'+': /* matches one or more times */
- case 0x80|'*': /* matches zero or more times */
- if (!(prest = pat_scan(p, pe, 0)))
- return 0;
- s--;
- /* take care of zero matches */
- if (p[-1] == (0x80 | '*')
- && do_gmatch(s, se, prest, pe, isfile))
- return 1;
- for (psub = p; ; psub = pnext) {
- pnext = pat_scan(psub, pe, 1);
- for (srest = s; srest <= se; srest++) {
- if (do_gmatch(s, srest,
- psub, pnext - 2, isfile)
- && (do_gmatch(srest, se,
- prest, pe, isfile)
- || (s != srest
- && do_gmatch(srest, se,
- p - 2, pe, isfile))))
- return 1;
- }
- if (pnext == prest)
- break;
- }
- return 0;
-
- case 0x80|'?': /* matches zero or once */
- case 0x80|'@': /* matches one of the patterns */
- if (!(prest = pat_scan(p, pe, 0)))
- return 0;
- s--;
- /* Take care of zero matches */
- if (p[-1] == (0x80 | '?')
- && do_gmatch(s, se, prest, pe, isfile))
- return 1;
- for (psub = p; ; psub = pnext) {
- pnext = pat_scan(psub, pe, 1);
- srest = prest == pe ? se : s;
- for (; srest <= se; srest++) {
- if (do_gmatch(s, srest,
- psub, pnext - 2, isfile)
- && do_gmatch(srest, se,
- prest, pe, isfile))
- return 1;
- }
- if (pnext == prest)
- break;
- }
- return 0;
-
- case 0x80|'!': /* matches none of the patterns */
- if (!(prest = pat_scan(p, pe, 0)))
- return 0;
- s--;
- for (srest = s; srest <= se; srest++) {
- int matched = 0;
-
- for (psub = p; ; psub = pnext) {
- pnext = pat_scan(psub, pe, 1);
- if (do_gmatch(s, srest,
- psub, pnext - 2, isfile))
- {
- matched = 1;
- break;
- }
- if (pnext == prest)
- break;
- }
- if (!matched && do_gmatch(srest, se,
- prest, pe, isfile))
- return 1;
- }
- return 0;
-#endif /* KSH */
-
- default:
- if (sc != p[-1])
- return 0;
- break;
- }
- }
- return s == se;
-}
-
-static const unsigned char *
-cclass(p, sub)
- const unsigned char *p;
- register int sub;
-{
- register int c, d, not, found = 0;
- const unsigned char *orig_p = p;
-
- if ((not = (ISMAGIC(*p) && *++p == NOT)))
- p++;
- do {
- c = *p++;
- if (ISMAGIC(c)) {
- c = *p++;
- if ((c & 0x80) && !ISMAGIC(c))
- c &= 0x7f;/* extended pattern matching: *+?@! */
- }
- if (c == '\0')
- /* No closing ] - act as if the opening [ was quoted */
- return sub == '[' ? orig_p : NULL;
- if (ISMAGIC(p[0]) && p[1] == '-'
- && (!ISMAGIC(p[2]) || p[3] != ']'))
- {
- p += 2; /* MAGIC- */
- d = *p++;
- if (ISMAGIC(d)) {
- d = *p++;
- if ((d & 0x80) && !ISMAGIC(d))
- d &= 0x7f;
- }
- /* POSIX says this is an invalid expression */
- if (c > d)
- return NULL;
- } else
- d = c;
- if (c == sub || (c <= sub && sub <= d))
- found = 1;
- } while (!(ISMAGIC(p[0]) && p[1] == ']'));
-
- return (found != not) ? p+2 : NULL;
-}
-
-/* Look for next ) or | (if match_sep) in *(foo|bar) pattern */
-const unsigned char *
-pat_scan(p, pe, match_sep)
- const unsigned char *p;
- const unsigned char *pe;
- int match_sep;
-{
- int nest = 0;
-
- for (; p < pe; p++) {
- if (!ISMAGIC(*p))
- continue;
- if ((*++p == /*(*/ ')' && nest-- == 0)
- || (*p == '|' && match_sep && nest == 0))
- return ++p;
- if ((*p & 0x80) && strchr("*+?@!", *p & 0x7f))
- nest++;
- }
- return (const unsigned char *) 0;
-}
-
-
-/* -------- qsort.c -------- */
-
-/*
- * quick sort of array of generic pointers to objects.
- */
-static void qsort1 ARGS((void **base, void **lim, int (*f)(void *, void *)));
-
-void
-qsortp(base, n, f)
- void **base; /* base address */
- size_t n; /* elements */
- int (*f) ARGS((void *, void *)); /* compare function */
-{
- qsort1(base, base + n, f);
-}
-
-#define swap2(a, b) {\
- register void *t; t = *(a); *(a) = *(b); *(b) = t;\
-}
-#define swap3(a, b, c) {\
- register void *t; t = *(a); *(a) = *(c); *(c) = *(b); *(b) = t;\
-}
-
-static void
-qsort1(base, lim, f)
- void **base, **lim;
- int (*f) ARGS((void *, void *));
-{
- register void **i, **j;
- register void **lptr, **hptr;
- size_t n;
- int c;
-
- top:
- n = (lim - base) / 2;
- if (n == 0)
- return;
- hptr = lptr = base+n;
- i = base;
- j = lim - 1;
-
- for (;;) {
- if (i < lptr) {
- if ((c = (*f)(*i, *lptr)) == 0) {
- lptr --;
- swap2(i, lptr);
- continue;
- }
- if (c < 0) {
- i += 1;
- continue;
- }
- }
-
- begin:
- if (j > hptr) {
- if ((c = (*f)(*hptr, *j)) == 0) {
- hptr ++;
- swap2(hptr, j);
- goto begin;
- }
- if (c > 0) {
- if (i == lptr) {
- hptr ++;
- swap3(i, hptr, j);
- i = lptr += 1;
- goto begin;
- }
- swap2(i, j);
- j -= 1;
- i += 1;
- continue;
- }
- j -= 1;
- goto begin;
- }
-
- if (i == lptr) {
- if (lptr-base >= lim-hptr) {
- qsort1(hptr+1, lim, f);
- lim = lptr;
- } else {
- qsort1(base, lptr, f);
- base = hptr+1;
- }
- goto top;
- }
-
- lptr -= 1;
- swap3(j, lptr, i);
- j = hptr -= 1;
- }
-}
-
-int
-xstrcmp(p1, p2)
- void *p1, *p2;
-{
- return (strcmp((char *)p1, (char *)p2));
-}
-
-/* Initialize a Getopt structure */
-void
-ksh_getopt_reset(go, flags)
- Getopt *go;
- int flags;
-{
- go->optind = 1;
- go->optarg = (char *) 0;
- go->p = 0;
- go->flags = flags;
- go->info = 0;
- go->buf[1] = '\0';
-}
-
-
-/* getopt() used for shell built-in commands, the getopts command, and
- * command line options.
- * A leading ':' in options means don't print errors, instead return '?'
- * or ':' and set go->optarg to the offending option character.
- * If GF_ERROR is set (and option doesn't start with :), errors result in
- * a call to bi_errorf().
- *
- * Non-standard features:
- * - ';' is like ':' in options, except the argument is optional
- * (if it isn't present, optarg is set to 0).
- * Used for 'set -o'.
- * - ',' is like ':' in options, except the argument always immediately
- * follows the option character (optarg is set to the null string if
- * the option is missing).
- * Used for 'read -u2', 'print -u2' and fc -40.
- * - '#' is like ':' in options, expect that the argument is optional
- * and must start with a digit. If the argument doesn't start with a
- * digit, it is assumed to be missing and normal option processing
- * continues (optarg is set to 0 if the option is missing).
- * Used for 'typeset -LZ4'.
- * - accepts +c as well as -c IF the GF_PLUSOPT flag is present. If an
- * option starting with + is accepted, the GI_PLUS flag will be set
- * in go->info. Once a - or + has been seen, all other options must
- * start with the same character.
- */
-int
-ksh_getopt(argv, go, options)
- char **argv;
- Getopt *go;
- const char *options;
-{
- char c;
- char *o;
-
- if (go->p == 0 || (c = argv[go->optind - 1][go->p]) == '\0') {
- char *arg = argv[go->optind], flag = arg ? *arg : '\0';
-
- go->p = 1;
- if (flag == '-' && arg[1] == '-' && arg[2] == '\0') {
- go->optind++;
- go->p = 0;
- go->info |= GI_MINUSMINUS;
- return EOF;
- }
- if (arg == (char *) 0
- || ((flag != '-' || (go->info & GI_PLUS))
- && (!(go->flags & GF_PLUSOPT) || (go->info & GI_MINUS)
- || flag != '+'))
- || (c = arg[1]) == '\0')
- {
- go->p = 0;
- return EOF;
- }
- go->optind++;
- go->info |= flag == '-' ? GI_MINUS : GI_PLUS;
- }
- go->p++;
- if (c == '?' || c == ':' || c == ';' || c == ',' || c == '#'
- || !(o = strchr(options, c)))
- {
- if (options[0] == ':') {
- go->buf[0] = c;
- go->optarg = go->buf;
- } else {
- warningf(TRUE, "%s%s-%c: unknown option",
- (go->flags & GF_NONAME) ? "" : argv[0],
- (go->flags & GF_NONAME) ? "" : ": ", c);
- if (go->flags & GF_ERROR)
- bi_errorf(null);
- }
- return '?';
- }
- /* : means argument must be present, may be part of option argument
- * or the next argument
- * ; same as : but argument may be missing
- * , means argument is part of option argument, and may be null.
- */
- if (*++o == ':' || *o == ';') {
- if (argv[go->optind - 1][go->p])
- go->optarg = argv[go->optind - 1] + go->p;
- else if (argv[go->optind])
- go->optarg = argv[go->optind++];
- else if (*o == ';')
- go->optarg = (char *) 0;
- else {
- if (options[0] == ':') {
- go->buf[0] = c;
- go->optarg = go->buf;
- return ':';
- }
- warningf(TRUE, "%s%s-`%c' requires argument",
- (go->flags & GF_NONAME) ? "" : argv[0],
- (go->flags & GF_NONAME) ? "" : ": ", c);
- if (go->flags & GF_ERROR)
- bi_errorf(null);
- return '?';
- }
- go->p = 0;
- } else if (*o == ',') {
- /* argument is attatched to option character, even if null */
- go->optarg = argv[go->optind - 1] + go->p;
- go->p = 0;
- } else if (*o == '#') {
- /* argument is optional and may be attatched or unattatched
- * but must start with a digit. optarg is set to 0 if the
- * argument is missing.
- */
- if (argv[go->optind - 1][go->p]) {
- if (digit(argv[go->optind - 1][go->p])) {
- go->optarg = argv[go->optind - 1] + go->p;
- go->p = 0;
- } else
- go->optarg = (char *) 0;;
- } else {
- if (argv[go->optind] && digit(argv[go->optind][0])) {
- go->optarg = argv[go->optind++];
- go->p = 0;
- } else
- go->optarg = (char *) 0;;
- }
- }
- return c;
-}
-
-/* print variable/alias value using necessary quotes
- * (POSIX says they should be suitable for re-entry...)
- * No trailing newline is printed.
- */
-void
-print_value_quoted(s)
- const char *s;
-{
- const char *p;
- int inquote = 0;
-
- /* Test if any quotes are needed */
- for (p = s; *p; p++)
- if (ctype(*p, C_QUOTE))
- break;
- if (!*p) {
- shprintf("%s", s);
- return;
- }
- for (p = s; *p; p++) {
- if (*p == '\'') {
- shprintf("'\\'" + 1 - inquote);
- inquote = 0;
- } else {
- if (!inquote) {
- shprintf("'");
- inquote = 1;
- }
- shf_putc(*p, shl_stdout);
- }
- }
- if (inquote)
- shprintf("'");
-}
-
-/* Print things in columns and rows - func() is called to format the ith
- * element
- */
-void
-print_columns(shf, n, func, arg, max_width)
- struct shf *shf;
- int n;
- char *(*func) ARGS((void *, int, char *, int));
- void *arg;
- int max_width;
-{
- char *str = (char *) alloc(max_width + 1, ATEMP);
- int i;
- int r, c;
- int rows, cols;
- int nspace;
-
- /* max_width + 1 for the space. Note that no space
- * is printed after the last column to avoid problems
- * with terminals that have auto-wrap.
- */
- cols = x_cols / (max_width + 1);
- if (!cols)
- cols = 1;
- rows = (n + cols - 1) / cols;
- if (n && cols > rows) {
- int tmp = rows;
-
- rows = cols;
- cols = tmp;
- if (rows > n)
- rows = n;
- }
-
- nspace = (x_cols - max_width * cols) / cols;
- if (nspace <= 0)
- nspace = 1;
- for (r = 0; r < rows; r++) {
- for (c = 0; c < cols; c++) {
- i = c * rows + r;
- if (i < n) {
- shf_fprintf(shf, "%-*s",
- max_width,
- (*func)(arg, i, str, max_width + 1));
- if (c + 1 < cols)
- shf_fprintf(shf, "%*s", nspace, null);
- }
- }
- shf_putchar('\n', shf);
- }
- afree(str, ATEMP);
-}
-
-/* Strip any nul bytes from buf - returns new length (nbytes - # of nuls) */
-int
-strip_nuls(buf, nbytes)
- char *buf;
- int nbytes;
-{
- char *dst;
-
- /* nbytes check because some systems (older freebsd's) have a buggy
- * memchr()
- */
- if (nbytes && (dst = memchr(buf, '\0', nbytes))) {
- char *end = buf + nbytes;
- char *p, *q;
-
- for (p = dst; p < end; p = q) {
- /* skip a block of nulls */
- while (++p < end && *p == '\0')
- ;
- /* find end of non-null block */
- if (!(q = memchr(p, '\0', end - p)))
- q = end;
- memmove(dst, p, q - p);
- dst += q - p;
- }
- *dst = '\0';
- return dst - buf;
- }
- return nbytes;
-}
-
-/* Copy at most dsize-1 bytes from src to dst, ensuring dst is null terminated.
- * Returns dst.
- */
-char *
-str_zcpy(dst, src, dsize)
- char *dst;
- const char *src;
- int dsize;
-{
- if (dsize > 0) {
- int len = strlen(src);
-
- if (len >= dsize)
- len = dsize - 1;
- memcpy(dst, src, len);
- dst[len] = '\0';
- }
- return dst;
-}
-
-/* Like read(2), but if read fails due to non-blocking flag, resets flag
- * and restarts read.
- */
-int
-blocking_read(fd, buf, nbytes)
- int fd;
- char *buf;
- int nbytes;
-{
- int ret;
- int tried_reset = 0;
-
- while ((ret = read(fd, buf, nbytes)) < 0) {
- if (!tried_reset && (errno == EAGAIN
-#ifdef EWOULDBLOCK
- || errno == EWOULDBLOCK
-#endif /* EWOULDBLOCK */
- ))
- {
- int oerrno = errno;
- if (reset_nonblock(fd) > 0) {
- tried_reset = 1;
- continue;
- }
- errno = oerrno;
- }
- break;
- }
- return ret;
-}
-
-/* Reset the non-blocking flag on the specified file descriptor.
- * Returns -1 if there was an error, 0 if non-blocking wasn't set,
- * 1 if it was.
- */
-int
-reset_nonblock(fd)
- int fd;
-{
- int flags;
- int blocking_flags;
-
- if ((flags = fcntl(fd, F_GETFL, 0)) < 0)
- return -1;
- /* With luck, the C compiler will reduce this to a constant */
- blocking_flags = 0;
-#ifdef O_NONBLOCK
- blocking_flags |= O_NONBLOCK;
-#endif /* O_NONBLOCK */
-#ifdef O_NDELAY
- blocking_flags |= O_NDELAY;
-#else /* O_NDELAY */
-# ifndef O_NONBLOCK
- blocking_flags |= FNDELAY; /* hope this exists... */
-# endif /* O_NONBLOCK */
-#endif /* O_NDELAY */
- if (!(flags & blocking_flags))
- return 0;
- flags &= ~blocking_flags;
- if (fcntl(fd, F_SETFL, flags) < 0)
- return -1;
- return 1;
-}
-
-
-#ifdef HAVE_SYS_PARAM_H
-# include <sys/param.h>
-#endif /* HAVE_SYS_PARAM_H */
-#ifndef MAXPATHLEN
-# define MAXPATHLEN PATH
-#endif /* MAXPATHLEN */
-
-/* Like getcwd(), except bsize is ignored if buf is 0 (MAXPATHLEN is used) */
-char *
-ksh_get_wd(buf, bsize)
- char *buf;
- int bsize;
-{
-#ifdef HAVE_GETWD
- extern char *getwd ARGS((char *));
- char *b;
- int len;
-
- if (buf && bsize > MAXPATHLEN)
- b = buf;
- else
- b = alloc(MAXPATHLEN + 1, ATEMP);
- if (!getwd(b)) {
- errno = EACCES;
- if (b != buf)
- afree(b, ATEMP);
- return (char *) 0;
- }
- len = strlen(b) + 1;
- if (!buf)
- b = aresize(b, len, ATEMP);
- else if (buf != b) {
- if (len > bsize) {
- errno = ERANGE;
- return (char *) 0;
- }
- memcpy(buf, b, len);
- afree(b, ATEMP);
- b = buf;
- }
-
- return b;
-#else /* HAVE_GETWD */
- char *b;
- char *ret;
-
- /* Assume getcwd() available */
- if (!buf) {
- bsize = MAXPATHLEN;
- b = alloc(MAXPATHLEN + 1, ATEMP);
- } else
- b = buf;
-
- ret = getcwd(b, bsize);
-
- if (!buf) {
- if (ret)
- ret = aresize(b, strlen(b) + 1, ATEMP);
- else
- afree(b, ATEMP);
- }
-
- return ret;
-#endif /* HAVE_GETWD */
-}
diff --git a/bin/pdksh/missing.c b/bin/pdksh/missing.c
deleted file mode 100644
index 7f507fe66b9..00000000000
--- a/bin/pdksh/missing.c
+++ /dev/null
@@ -1,271 +0,0 @@
-/* $OpenBSD: missing.c,v 1.3 1997/06/19 13:58:45 kstailey Exp $ */
-
-/*
- * Routines which may be missing on some machines
- */
-
-#include "sh.h"
-#include "ksh_stat.h"
-#include "ksh_dir.h"
-
-
-#ifndef HAVE_MEMSET
-void *
-memset(d, c, n)
- void *d;
- int c;
- size_t n;
-{
- unsigned char *p = (unsigned char *) d;
-
- /* Not amazingly fast.. */
- for (; n > 0; --n)
- *p++ = c;
- return d;
-}
-#endif /* !HAVE_MEMSET */
-
-#if !defined(HAVE_MEMMOVE) && !defined(HAVE_BCOPY)
-void *
-memmove(d, s, n)
- void *d;
- const void *s;
- size_t n;
-{
- char *dp = (char *) d, *sp = (char *) s;
-
- if (n <= 0)
- ;
- else if (dp < sp)
- do
- *dp++ = *sp++;
- while (--n > 0);
- else if (dp > sp) {
- dp += n;
- sp += n;
- do
- *--dp = *--sp;
- while (--n > 0);
- }
- return d;
-}
-#endif /* !HAVE_MEMMOVE && !HAVE_BCOPY */
-
-
-#ifndef HAVE_STRCASECMP
-/*
- * Case insensitive string compare routines, same semantics as str[n]cmp()
- * (assumes ASCII..).
- */
-static const char ichars[256] = {
- 0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
- 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
- 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
- 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
- 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
- 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
- 0x40, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
- 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
- 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
- 'x', 'y', 'z', 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
- 0x60, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
- 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
- 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
- 'x', 'y', 'z', 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
- 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
- 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
- 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
- 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
- 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
- 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
- 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
- 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
- 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
- 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
- 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
- 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
- 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
- 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
- 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
- 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
- };
-
-int
-strcasecmp(s1, s2)
- const char *s1;
- const char *s2;
-{
- const unsigned char *us1 = (const unsigned char *) s1;
- const unsigned char *us2 = (const unsigned char *) s2;
-
- while (ichars[*us1] == ichars[*us2++])
- if (!*us1++)
- return 0;
-
- return ichars[*us1] - ichars[*--us2];
-}
-
-int
-strncasecmp(s1, s2, n)
- const char *s1;
- const char *s2;
- int n;
-{
- const unsigned char *us1 = (const unsigned char *) s1;
- const unsigned char *us2 = (const unsigned char *) s2;
-
- while (--n >= 0 && ichars[*us1] == ichars[*us2++])
- if (!*us1++)
- return 0;
-
- return n < 0 ? 0 : ichars[*us1] - ichars[*--us2];
-}
-#endif /* HAVE_STRCASECMP */
-
-
-#ifndef HAVE_STRSTR
-char *
-strstr(s, p)
- const char *s;
- const char *p;
-{
- int len;
-
- if (s && p)
- for (len = strlen(p); *s; s++)
- if (*s == *p && strncmp(s, p, len) == 0)
- return (char *) s;
-
- return 0;
-}
-#endif /* HAVE_STRSTR */
-
-
-#ifndef HAVE_STRERROR
-char *
-strerror(err)
- int err;
-{
- static char buf[64];
-# ifdef HAVE_SYS_ERRLIST
-# ifndef SYS_ERRLIST_DECLARED
- extern int sys_nerr;
- extern char *sys_errlist[];
-# endif
- char *p;
-
- if (err < 0 || err >= sys_nerr)
- shf_snprintf(p = buf, sizeof(buf), "Unknown system error %d",
- err);
- else
- p = sys_errlist[err];
- return p;
-# else /* HAVE_SYS_ERRLIST */
- switch (err) {
- case EINVAL:
- return "Invalid argument";
- case EACCES:
- return "Permission denied";
- case ESRCH:
- return "No such process";
- case EPERM:
- return "Not owner";
- case ENOENT:
- return "No such file or directory";
- case ENOTDIR:
- return "Not a directory";
- case ENOEXEC:
- return "Exec format error";
- case ENOMEM:
- return "Not enough memory";
- case E2BIG:
- return "Argument list too long";
- default:
- shf_snprintf(buf, sizeof(buf), "Unknown system error %d", err);
- return buf;
- }
-# endif /* HAVE_SYS_ERRLIST */
-}
-#endif /* !HAVE_STRERROR */
-
-
-#ifdef TIMES_BROKEN
-# include "ksh_time.h"
-# include "ksh_times.h"
-# ifdef HAVE_GETRUSAGE
-# include <sys/resource.h>
-# else /* HAVE_GETRUSAGE */
-# include <sys/timeb.h>
-# endif /* HAVE_GETRUSAGE */
-
-clock_t
-ksh_times(tms)
- struct tms *tms;
-{
- static clock_t base_sec;
- clock_t rv;
-
-# ifdef HAVE_GETRUSAGE
- {
- struct timeval tv;
- struct rusage ru;
-
- getrusage(RUSAGE_SELF, &ru);
- tms->tms_utime = ru.ru_utime.tv_sec * CLK_TCK
- + ru.ru_utime.tv_usec * CLK_TCK / 1000000;
- tms->tms_stime = ru.ru_stime.tv_sec * CLK_TCK
- + ru.ru_stime.tv_usec * CLK_TCK / 1000000;
-
- getrusage(RUSAGE_CHILDREN, &ru);
- tms->tms_cutime = ru.ru_utime.tv_sec * CLK_TCK
- + ru.ru_utime.tv_usec * CLK_TCK / 1000000;
- tms->tms_cstime = ru.ru_stime.tv_sec * CLK_TCK
- + ru.ru_stime.tv_usec * CLK_TCK / 1000000;
-
- gettimeofday(&tv, (struct timezone *) 0);
- if (base_sec == 0)
- base_sec = tv.tv_sec;
- rv = (tv.tv_sec - base_sec) * CLK_TCK;
- rv += tv.tv_usec * CLK_TCK / 1000000;
- }
-# else /* HAVE_GETRUSAGE */
- /* Assume times() available, but always returns 0
- * (also assumes ftime() available)
- */
- {
- struct timeb tb;
-
- if (times(tms) == (clock_t) -1)
- return (clock_t) -1;
- ftime(&tb);
- if (base_sec == 0)
- base_sec = tb.time;
- rv = (tb.time - base_sec) * CLK_TCK;
- rv += tb.millitm * CLK_TCK / 1000;
- }
-# endif /* HAVE_GETRUSAGE */
- return rv;
-}
-#endif /* TIMES_BROKEN */
-
-#ifdef OPENDIR_DOES_NONDIR
-/* Prevent opendir() from attempting to open non-directories. Such
- * behavior can cause problems if it attempts to open special devices...
- */
-DIR *
-ksh_opendir(d)
- const char *d;
-{
- struct stat statb;
-
- if (stat(d, &statb) != 0)
- return (DIR *) 0;
- if (!S_ISDIR(statb.st_mode)) {
- errno = ENOTDIR;
- return (DIR *) 0;
- }
- return opendir(d);
-}
-#endif /* OPENDIR_DOES_NONDIR */
diff --git a/bin/pdksh/path.c b/bin/pdksh/path.c
deleted file mode 100644
index d0a08761d9a..00000000000
--- a/bin/pdksh/path.c
+++ /dev/null
@@ -1,346 +0,0 @@
-/* $OpenBSD: path.c,v 1.3 1997/06/19 13:58:46 kstailey Exp $ */
-
-#include "sh.h"
-#include "ksh_stat.h"
-
-/*
- * Contains a routine to search a : seperated list of
- * paths (a la CDPATH) and make appropiate file names.
- * Also contains a routine to simplify .'s and ..'s out of
- * a path name.
- *
- * Larry Bouzane (larry@cs.mun.ca)
- */
-
-/*
- * $Log: path.c,v $
- * Revision 1.3 1997/06/19 13:58:46 kstailey
- * back out
- *
- * Revision 1.1.1.1 1996/08/14 06:19:11 downsj
- * Import pdksh 5.2.7.
- *
- * Revision 1.2 1994/05/19 18:32:40 michael
- * Merge complete, stdio replaced, various fixes. (pre autoconf)
- *
- * Revision 1.1 1994/04/06 13:14:03 michael
- * Initial revision
- *
- * Revision 4.2 1990/12/06 18:05:24 larry
- * Updated test code to reflect parameter change.
- * Fixed problem with /a/./.dir being simplified to /a and not /a/.dir due
- * to *(cur+2) == *f test instead of the correct cur+2 == f
- *
- * Revision 4.1 90/10/29 14:42:19 larry
- * base MUN version
- *
- * Revision 3.1.0.4 89/02/16 20:28:36 larry
- * Forgot to set *pathlist to NULL when last changed make_path().
- *
- * Revision 3.1.0.3 89/02/13 20:29:55 larry
- * Fixed up cd so that it knew when a node from CDPATH was used and would
- * print a message only when really necessary.
- *
- * Revision 3.1.0.2 89/02/13 17:51:22 larry
- * Merged with Eric Gisin's version.
- *
- * Revision 3.1.0.1 89/02/13 17:50:58 larry
- * *** empty log message ***
- *
- * Revision 3.1 89/02/13 17:49:28 larry
- * *** empty log message ***
- *
- */
-
-#ifdef S_ISLNK
-static char *do_phys_path ARGS((XString *xsp, char *xp, const char *path));
-#endif /* S_ISLNK */
-
-/*
- * Makes a filename into result using the following algorithm.
- * - make result NULL
- * - if file starts with '/', append file to result & set cdpathp to NULL
- * - if file starts with ./ or ../ append cwd and file to result
- * and set cdpathp to NULL
- * - if the first element of cdpathp doesnt start with a '/' xx or '.' xx
- * then cwd is appended to result.
- * - the first element of cdpathp is appended to result
- * - file is appended to result
- * - cdpathp is set to the start of the next element in cdpathp (or NULL
- * if there are no more elements.
- * The return value indicates whether a non-null element from cdpathp
- * was appened to result.
- */
-int
-make_path(cwd, file, cdpathp, xsp, phys_pathp)
- const char *cwd;
- const char *file;
- char **cdpathp; /* & of : seperated list */
- XString *xsp;
- int *phys_pathp;
-{
- int rval = 0;
- int use_cdpath = 1;
- char *plist;
- int len;
- int plen = 0;
- char *xp = Xstring(*xsp, xp);
-
- if (!file)
- file = null;
-
- if (!ISRELPATH(file)) {
- *phys_pathp = 0;
- use_cdpath = 0;
- } else {
- if (file[0] == '.') {
- char c = file[1];
-
- if (c == '.')
- c = file[2];
- if (ISDIRSEP(c) || c == '\0')
- use_cdpath = 0;
- }
-
- plist = *cdpathp;
- if (!plist)
- use_cdpath = 0;
- else if (use_cdpath) {
- char *pend;
-
- for (pend = plist; *pend && *pend != PATHSEP; pend++)
- ;
- plen = pend - plist;
- *cdpathp = *pend ? ++pend : (char *) 0;
- }
-
- if ((use_cdpath == 0 || !plen || ISRELPATH(plist))
- && (cwd && *cwd))
- {
- len = strlen(cwd);
- XcheckN(*xsp, xp, len);
- memcpy(xp, cwd, len);
- xp += len;
- if (!ISDIRSEP(cwd[len - 1]))
- Xput(*xsp, xp, DIRSEP);
- }
- *phys_pathp = Xlength(*xsp, xp);
- if (use_cdpath && plen) {
- XcheckN(*xsp, xp, plen);
- memcpy(xp, plist, plen);
- xp += plen;
- if (!ISDIRSEP(plist[plen - 1]))
- Xput(*xsp, xp, DIRSEP);
- rval = 1;
- }
- }
-
- len = strlen(file) + 1;
- XcheckN(*xsp, xp, len);
- memcpy(xp, file, len);
-
- if (!use_cdpath)
- *cdpathp = (char *) 0;
-
- return rval;
-}
-
-/*
- * Simplify pathnames containing "." and ".." entries.
- * ie, simplify_path("/a/b/c/./../d/..") returns "/a/b"
- */
-void
-simplify_path(path)
- char *path;
-{
- char *cur;
- char *t;
- int isrooted;
- char *very_start = path;
- char *start;
-
- if (!*path)
- return;
-
- if ((isrooted = ISROOTEDPATH(path)))
- very_start++;
-#ifdef OS2
- if (path[0] && path[1] == ':') /* skip a: */
- very_start += 2;
-#endif /* OS2 */
-
- /* Before After
- * /foo/ /foo
- * /foo/../../bar /bar
- * /foo/./blah/.. /foo
- * . .
- * .. ..
- * ./foo foo
- * foo/../../../bar ../../bar
- * OS2:
- * a:/foo/../.. a:/
- * a:. a:
- * a:.. a:..
- * a:foo/../../blah a:../blah
- */
-
- for (cur = t = start = very_start; ; ) {
- /* treat multiple '/'s as one '/' */
- while (ISDIRSEP(*t))
- t++;
-
- if (*t == '\0') {
- if (cur == path)
- /* convert empty path to dot */
- *cur++ = '.';
- *cur = '\0';
- break;
- }
-
- if (t[0] == '.') {
- if (!t[1] || ISDIRSEP(t[1])) {
- t += 1;
- continue;
- } else if (t[1] == '.' && (!t[2] || ISDIRSEP(t[2]))) {
- if (!isrooted && cur == start) {
- if (cur != very_start)
- *cur++ = DIRSEP;
- *cur++ = '.';
- *cur++ = '.';
- start = cur;
- } else if (cur != start)
- while (--cur > start && !ISDIRSEP(*cur))
- ;
- t += 2;
- continue;
- }
- }
-
- if (cur != very_start)
- *cur++ = DIRSEP;
-
- /* find/copy next component of pathname */
- while (*t && !ISDIRSEP(*t))
- *cur++ = *t++;
- }
-}
-
-
-void
-set_current_wd(path)
- char *path;
-{
- int len;
- char *p = path;
-
- if (!p && !(p = ksh_get_wd((char *) 0, 0)))
- p = null;
-
- len = strlen(p) + 1;
-
- if (len > current_wd_size)
- current_wd = aresize(current_wd, current_wd_size = len, APERM);
- memcpy(current_wd, p, len);
- if (p != path && p != null)
- afree(p, ATEMP);
-}
-
-#ifdef S_ISLNK
-char *
-get_phys_path(path)
- const char *path;
-{
- XString xs;
- char *xp;
-
- Xinit(xs, xp, strlen(path) + 1, ATEMP);
-
- xp = do_phys_path(&xs, xp, path);
-
- if (!xp)
- return (char *) 0;
-
- if (Xlength(xs, xp) == 0)
- Xput(xs, xp, DIRSEP);
- Xput(xs, xp, '\0');
-
- return Xclose(xs, xp);
-}
-
-static char *
-do_phys_path(xsp, xp, path)
- XString *xsp;
- char *xp;
- const char *path;
-{
- const char *p, *q;
- int len, llen;
- int savepos;
- char lbuf[PATH];
-
- Xcheck(*xsp, xp);
- for (p = path; p; p = q) {
- while (ISDIRSEP(*p))
- p++;
- if (!*p)
- break;
- len = (q = ksh_strchr_dirsep(p)) ? q - p : strlen(p);
- if (len == 1 && p[0] == '.')
- continue;
- if (len == 2 && p[0] == '.' && p[1] == '.') {
- while (xp > Xstring(*xsp, xp)) {
- xp--;
- if (ISDIRSEP(*xp))
- break;
- }
- continue;
- }
-
- savepos = Xsavepos(*xsp, xp);
- Xput(*xsp, xp, DIRSEP);
- XcheckN(*xsp, xp, len + 1);
- memcpy(xp, p, len);
- xp += len;
- *xp = '\0';
-
- llen = readlink(Xstring(*xsp, xp), lbuf, sizeof(lbuf) - 1);
- if (llen < 0) {
- /* EINVAL means it wasn't a symlink... */
- if (errno != EINVAL)
- return (char *) 0;
- continue;
- }
- lbuf[llen] = '\0';
-
- /* If absolute path, start from scratch.. */
- xp = ISABSPATH(lbuf) ? Xstring(*xsp, xp)
- : Xrestpos(*xsp, xp, savepos);
- if (!(xp = do_phys_path(xsp, xp, lbuf)))
- return (char *) 0;
- }
- return xp;
-}
-#endif /* S_ISLNK */
-
-#ifdef TEST
-
-main(argc, argv)
-{
- int rv;
- char *cp, cdpath[256], pwd[256], file[256], result[256];
-
- printf("enter CDPATH: "); gets(cdpath);
- printf("enter PWD: "); gets(pwd);
- while (1) {
- if (printf("Enter file: "), gets(file) == 0)
- return 0;
- cp = cdpath;
- do {
- rv = make_path(pwd, file, &cp, result, sizeof(result));
- printf("make_path returns (%d), \"%s\" ", rv, result);
- simplify_path(result);
- printf("(simpifies to \"%s\")\n", result);
- } while (cp);
- }
-}
-#endif /* TEST */
diff --git a/bin/pdksh/proto.h b/bin/pdksh/proto.h
deleted file mode 100644
index 608b451f593..00000000000
--- a/bin/pdksh/proto.h
+++ /dev/null
@@ -1,292 +0,0 @@
-/* $OpenBSD: proto.h,v 1.3 1996/11/21 07:59:34 downsj Exp $ */
-
-/*
- * prototypes for PD-KSH
- * originally generated using "cproto.c 3.5 92/04/11 19:28:01 cthuang "
- * $From: proto.h,v 1.3 1994/05/19 18:32:40 michael Exp michael $
- */
-
-/* alloc.c */
-Area * ainit ARGS((Area *ap));
-void afreeall ARGS((Area *ap));
-void * alloc ARGS((size_t size, Area *ap));
-void * aresize ARGS((void *ptr, size_t size, Area *ap));
-void afree ARGS((void *ptr, Area *ap));
-/* c_ksh.c */
-int c_hash ARGS((char **wp));
-int c_cd ARGS((char **wp));
-int c_pwd ARGS((char **wp));
-int c_print ARGS((char **wp));
-int c_whence ARGS((char **wp));
-int c_command ARGS((char **wp));
-int c_typeset ARGS((char **wp));
-int c_alias ARGS((char **wp));
-int c_unalias ARGS((char **wp));
-int c_let ARGS((char **wp));
-int c_jobs ARGS((char **wp));
-int c_fgbg ARGS((char **wp));
-int c_kill ARGS((char **wp));
-void getopts_reset ARGS((int val));
-int c_getopts ARGS((char **wp));
-int c_bind ARGS((char **wp));
-/* c_sh.c */
-int c_label ARGS((char **wp));
-int c_shift ARGS((char **wp));
-int c_umask ARGS((char **wp));
-int c_dot ARGS((char **wp));
-int c_wait ARGS((char **wp));
-int c_read ARGS((char **wp));
-int c_eval ARGS((char **wp));
-int c_trap ARGS((char **wp));
-int c_brkcont ARGS((char **wp));
-int c_exitreturn ARGS((char **wp));
-int c_set ARGS((char **wp));
-int c_unset ARGS((char **wp));
-int c_ulimit ARGS((char **wp));
-int c_times ARGS((char **wp));
-int timex ARGS((struct op *t, int f));
-int c_exec ARGS((char **wp));
-int c_builtin ARGS((char **wp));
-/* c_test.c */
-int c_test ARGS((char **wp));
-/* edit.c: most prototypes in edit.h */
-void x_init ARGS((void));
-int x_read ARGS((char *buf, size_t len));
-void set_editmode ARGS((const char *ed));
-/* emacs.c: most prototypes in edit.h */
-int x_bind ARGS((const char *a1, const char *a2, int macro,
- int list));
-/* eval.c */
-char * substitute ARGS((const char *cp, int f));
-char ** eval ARGS((char **ap, int f));
-char * evalstr ARGS((char *cp, int f));
-char * evalonestr ARGS((char *cp, int f));
-char *debunk ARGS((char *dp, const char *sp));
-void expand ARGS((char *cp, XPtrV *wp, int f));
-int glob_str ARGS((char *cp, XPtrV *wp, int markdirs));
-/* exec.c */
-int fd_clexec ARGS((int fd));
-int execute ARGS((struct op * volatile t, volatile int flags));
-int shcomexec ARGS((char **wp));
-struct tbl * findfunc ARGS((const char *name, unsigned int h, int create));
-int define ARGS((const char *name, struct op *t));
-void builtin ARGS((const char *name, int (*func)(char **)));
-struct tbl * findcom ARGS((const char *name, int flags));
-void flushcom ARGS((int all));
-char * search ARGS((const char *name, const char *path, int mode,
- int *errnop));
-int search_access ARGS((const char *path, int mode, int *errnop));
-int pr_menu ARGS((char *const *ap));
-/* expr.c */
-int evaluate ARGS((const char *expr, long *rval, int error_ok));
-int v_evaluate ARGS((struct tbl *vp, const char *expr, volatile int error_ok));
-/* history.c */
-void init_histvec ARGS((void));
-void hist_init ARGS((Source *s));
-void hist_finish ARGS((void));
-void histsave ARGS((int lno, const char *cmd, int dowrite));
-#ifdef HISTORY
-int c_fc ARGS((register char **wp));
-void sethistsize ARGS((int n));
-void sethistfile ARGS((const char *name));
-# ifdef EASY_HISTORY
-void histappend ARGS((const char *cmd, int nl_seperate));
-# endif
-char ** histpos ARGS((void));
-int histN ARGS((void));
-int histnum ARGS((int n));
-int findhist ARGS((int start, int fwd, const char *str,
- int anchored));
-#endif /* HISTORY */
-/* io.c */
-void errorf ARGS((const char *fmt, ...))
- GCC_FUNC_ATTR2(noreturn, format(printf, 1, 2));
-void warningf ARGS((int fileline, const char *fmt, ...))
- GCC_FUNC_ATTR(format(printf, 2, 3));
-void bi_errorf ARGS((const char *fmt, ...))
- GCC_FUNC_ATTR(format(printf, 1, 2));
-void internal_errorf ARGS((int jump, const char *fmt, ...))
- GCC_FUNC_ATTR(format(printf, 2, 3));
-void error_prefix ARGS((int fileline));
-void shellf ARGS((const char *fmt, ...))
- GCC_FUNC_ATTR(format(printf, 1, 2));
-void shprintf ARGS((const char *fmt, ...))
- GCC_FUNC_ATTR(format(printf, 1, 2));
-int can_seek ARGS((int fd));
-void initio ARGS((void));
-int ksh_dup2 ARGS((int ofd, int nfd, int errok));
-int savefd ARGS((int fd, int noclose));
-void restfd ARGS((int fd, int ofd));
-void openpipe ARGS((int *pv));
-void closepipe ARGS((int *pv));
-int check_fd ARGS((char *name, int mode, const char **emsgp));
-#ifdef KSH
-void coproc_init ARGS((void));
-void coproc_read_close ARGS((int fd));
-void coproc_readw_close ARGS((int fd));
-void coproc_write_close ARGS((int fd));
-int coproc_getfd ARGS((int mode, const char **emsgp));
-void coproc_cleanup ARGS((int reuse));
-#endif /* KSH */
-struct temp *maketemp ARGS((Area *ap));
-/* jobs.c */
-void j_init ARGS((int mflagset));
-void j_exit ARGS((void));
-void j_change ARGS((void));
-int exchild ARGS((struct op *t, int flags, int close_fd));
-void startlast ARGS((void));
-int waitlast ARGS((void));
-int waitfor ARGS((const char *cp, int *sigp));
-int j_kill ARGS((const char *cp, int sig));
-int j_resume ARGS((const char *cp, int bg));
-int j_jobs ARGS((const char *cp, int slp, int nflag));
-void j_notify ARGS((void));
-pid_t j_async ARGS((void));
-int j_stopped_running ARGS((void));
-/* lex.c */
-int yylex ARGS((int cf));
-void yyerror ARGS((const char *fmt, ...))
- GCC_FUNC_ATTR2(noreturn, format(printf, 1, 2));
-Source * pushs ARGS((int type, Area *areap));
-void set_prompt ARGS((int to, Source *s));
-void pprompt ARGS((const char *cp, int ntruncate));
-/* mail.c */
-#ifdef KSH
-void mcheck ARGS((void));
-void mbset ARGS((char *p));
-void mpset ARGS((char *mptoparse));
-#endif /* KSH */
-/* main.c */
-int include ARGS((const char *name, int argc, char **argv,
- int intr_ok));
-int command ARGS((const char *comm));
-int shell ARGS((Source *volatile s, int volatile toplevel));
-void unwind ARGS((int i)) GCC_FUNC_ATTR(noreturn);
-void newenv ARGS((int type));
-void quitenv ARGS((void));
-void cleanup_parents_env ARGS((void));
-void cleanup_proc_env ARGS((void));
-void aerror ARGS((Area *ap, const char *msg))
- GCC_FUNC_ATTR(noreturn);
-/* misc.c */
-void setctypes ARGS((const char *s, int t));
-void initctypes ARGS((void));
-char * ulton ARGS((unsigned long n, int base));
-char * str_save ARGS((const char *s, Area *ap));
-char * str_nsave ARGS((const char *s, int n, Area *ap));
-int option ARGS((const char *n));
-char * getoptions ARGS((void));
-void change_flag ARGS((enum sh_flag f, int what, int newval));
-int parse_args ARGS((char **argv, int what, int *setargsp));
-int getn ARGS((const char *as, int *ai));
-int bi_getn ARGS((const char *as, int *ai));
-char * strerror ARGS((int i));
-int gmatch ARGS((const char *s, const char *p, int isfile));
-int has_globbing ARGS((const char *xp, const char *xpe));
-const unsigned char *pat_scan ARGS((const unsigned char *p,
- const unsigned char *pe, int match_sep));
-void qsortp ARGS((void **base, size_t n, int (*f)(void *, void *)));
-int xstrcmp ARGS((void *p1, void *p2));
-void ksh_getopt_reset ARGS((Getopt *go, int));
-int ksh_getopt ARGS((char **argv, Getopt *go, const char *options));
-void print_value_quoted ARGS((const char *s));
-void print_columns ARGS((struct shf *shf, int n,
- char *(*func)(void *, int, char *, int),
- void *arg, int max_width));
-int strip_nuls ARGS((char *buf, int nbytes));
-char *str_zcpy ARGS((char *dst, const char *src, int dsize));
-int blocking_read ARGS((int fd, char *buf, int nbytes));
-int reset_nonblock ARGS((int fd));
-char *ksh_get_wd ARGS((char *buf, int bsize));
-/* path.c */
-int make_path ARGS((const char *cwd, const char *file,
- char **pathlist, XString *xsp, int *phys_pathp));
-void simplify_path ARGS((char *path));
-char *get_phys_path ARGS((const char *path));
-void set_current_wd ARGS((char *path));
-/* syn.c */
-void initkeywords ARGS((void));
-struct op * compile ARGS((Source *s));
-/* table.c */
-unsigned int hash ARGS((const char *n));
-void tinit ARGS((struct table *tp, Area *ap, int tsize));
-struct tbl * tsearch ARGS((struct table *tp, const char *n, unsigned int h));
-struct tbl * tenter ARGS((struct table *tp, const char *n, unsigned int h));
-void tdelete ARGS((struct tbl *p));
-void twalk ARGS((struct tstate *ts, struct table *tp));
-struct tbl * tnext ARGS((struct tstate *ts));
-struct tbl ** tsort ARGS((struct table *tp));
-/* trace.c */
-/* trap.c */
-void inittraps ARGS((void));
-#ifdef KSH
-void alarm_init ARGS((void));
-#endif /* KSH */
-Trap * gettrap ARGS((const char *name));
-RETSIGTYPE trapsig ARGS((int i));
-void intrcheck ARGS((void));
-int fatal_trap_check ARGS((void));
-int trap_pending ARGS((void));
-void runtraps ARGS((int intr));
-void runtrap ARGS((Trap *p));
-void cleartraps ARGS((void));
-void restoresigs ARGS((void));
-void settrap ARGS((Trap *p, char *s));
-int block_pipe ARGS((void));
-void restore_pipe ARGS((int restore_dfl));
-int setsig ARGS((Trap *p, handler_t f, int flags));
-void setexecsig ARGS((Trap *p, int restore));
-/* tree.c */
-int fptreef ARGS((struct shf *f, int indent, const char *fmt, ...));
-char * snptreef ARGS((char *s, int n, const char *fmt, ...));
-struct op * tcopy ARGS((struct op *t, Area *ap));
-char * wdcopy ARGS((const char *wp, Area *ap));
-char * wdscan ARGS((const char *wp, int c));
-void tfree ARGS((struct op *t, Area *ap));
-/* var.c */
-void newblock ARGS((void));
-void popblock ARGS((void));
-void initvar ARGS((void));
-struct tbl * global ARGS((const char *n));
-struct tbl * local ARGS((const char *n, bool_t copy));
-char * str_val ARGS((struct tbl *vp));
-long intval ARGS((struct tbl *vp));
-void setstr ARGS((struct tbl *vq, const char *s));
-struct tbl *setint_v ARGS((struct tbl *vq, struct tbl *vp));
-void setint ARGS((struct tbl *vq, long n));
-int getint ARGS((struct tbl *vp, long *nump));
-struct tbl * typeset ARGS((const char *var, Tflag set, Tflag clr, int field, int base));
-void unset ARGS((struct tbl *vp, int array_ref));
-char * skip_varname ARGS((const char *s, int aok));
-char *skip_wdvarname ARGS((const char *s, int aok));
-int is_wdvarname ARGS((const char *s, int aok));
-int is_wdvarassign ARGS((const char *s));
-char ** makenv ARGS((void));
-int array_ref_len ARGS((const char *cp));
-char * arrayname ARGS((const char *str));
-void set_array ARGS((const char *var, int reset, char **vals));
-/* version.c */
-/* vi.c: see edit.h */
-
-
-/* Hack to avoid billions of compile warnings on SunOS 4.1.x */
-#if defined(MUN) && defined(sun) && !defined(__svr4__)
-extern void bcopy ARGS((const void *src, void *dst, size_t size));
-extern int fclose ARGS((FILE *fp));
-extern int fprintf ARGS((FILE *fp, const char *fmt, ...));
-extern int fread ARGS((void *buf, int size, int num, FILE *fp));
-extern int ioctl ARGS((int fd, int request, void *arg));
-extern int killpg ARGS((int pgrp, int sig));
-extern int nice ARGS((int n));
-extern int readlink ARGS((const char *path, char *buf, int bufsize));
-extern int setpgrp ARGS((int pid, int pgrp));
-extern int strcasecmp ARGS((const char *s1, const char *s2));
-extern int tolower ARGS((int));
-extern int toupper ARGS((int));
-/* Include files aren't included yet */
-extern int getrlimit ARGS(( /* int resource, struct rlimit *rpl */ ));
-extern int getrusage ARGS(( /* int who, struct rusage *rusage */ ));
-extern int gettimeofday ARGS(( /* struct timeval *tv, struct timezone *tz */ ));
-extern int setrlimit ARGS(( /* int resource, struct rlimit *rlp */ ));
-extern int lstat ARGS(( /* const char *path, struct stat *buf */ ));
-#endif
diff --git a/bin/pdksh/sh.1tbl b/bin/pdksh/sh.1tbl
deleted file mode 100644
index 7d0eeacbc9e..00000000000
--- a/bin/pdksh/sh.1tbl
+++ /dev/null
@@ -1,2372 +0,0 @@
-'\" t
-.\" $OpenBSD: sh.1tbl,v 1.3 1997/08/05 21:49:56 grr Exp $
-.\"{{{}}}
-.\"{{{ Notes about man page
-.\" - use the pseudo-macros .sh( and .sh) to begin and end sh-specific
-.\" text and .ksh( and .ksh) for ksh specific text.
-.\" - put i.e., e.g. and etc. in italics
-.\"}}}
-.\"{{{ To do
-.\" todo: Things not covered that should be:
-.\" - distinguish (POSIX) special built-in's, (POSIX) regular built-in's,
-.\" and sh/ksh weirdo built-in's (put S,R,X superscripts after command
-.\" name in built-in commands section?)
-.\" - need to be consistent about notation for `See section-name', `
-.\" See description of foobar command', `See section section-name', etc.
-.\" - need to use the term `external command' meaning `a command that is
-.\" executed using execve(2)' (as opposed to a built-in command or
-.\" function) for more clear description.
-.\"}}}
-.\"{{{ Title
-.TH SH 1 "August 19, 1996" "" "User commands"
-.\"}}}
-.\"{{{ Name
-.SH NAME
-sh \- Public domain Bourne shell
-.\"}}}
-.\"{{{ Synopsis
-.SH SYNOPSIS
-.ad l
-\fBsh\fP
-[\fB\(+-abCefhikmnprsuvxX\fP] [\fB\(+-o\fP \fIoption\fP] [ [ \fB\-c\fP \fIcommand-string\fP [\fIcommand-name\fP] | \fB\-s\fP | \fIfile\fP ] [\fIargument\fP ...] ]
-.ad b
-.\"}}}
-.\"{{{ Description
-.SH DESCRIPTION
-\fBsh\fP is a reimplementation of the Bourne shell, a command
-interpreter for both interactive and script use.
-.\"{{{ Shell Startup
-.SS "Shell Startup"
-The following options can be specified only on the command line:
-.IP "\fB\-c\fP \fIcommand-string\fP"
-the shell executes the command(s) contained in \fIcommand-string\fP
-.IP \fB\-i\fP
-interactive mode \(em see below
-.IP \fB\-l\fP
-login shell \(em see below
-interactive mode \(em see below
-.IP \fB\-s\fP
-the shell reads commands from standard input; all non-option arguments
-are positional parameters
-.IP \fB\-r\fP
-restricted mode \(em see below
-.PP
-In addition to the above, the options described in the \fBset\fP built-in
-command can also be used on the command line.
-.PP
-If neither the \fB\-c\fP nor the \fB\-s\fP options are specified, the
-first non-option argument specifies the name of a file the shell reads
-commands from; if there are no non-option arguments, the shell reads
-commands from standard input.
-The name of the shell (\fIi.e.\fP, the contents of the \fB$0\fP) parameter
-is determined as follows: if the \fB\-c\fP option is used and there is
-a non-option argument, it is used as the name; if commands are being
-read from a file, the file is used as the name; otherwise the name
-the shell was called with (\fIi.e.\fP, argv[0]) is used.
-.PP
-A shell is \fBinteractive\fP if the \fB\-i\fP option is used or
-if both standard input and standard error are attached to a tty.
-An interactive shell has job control enabled (if available),
-ignores the INT, QUIT and TERM signals, and prints prompts before
-reading input (see \fBPS1\fP and \fBPS2\fP parameters).
-For non-interactive shells, the \fBtrackall\fP option is on by default
-(see \fBset\fP command below).
-.PP
-A shell is \fBrestricted\fP if the \fB\-r\fP option is used or if either
-the basename of the name the shell is invoked with or the \fBSHELL\fP
-parameter match the pattern *r*sh (\fIe.g.\fP, rsh, rksh, rpdksh, \fIetc.\fP).
-The following restrictions come into effect after the shell processes
-any profile and \fB$ENV\fP files:
-.nr P2 \n(PD
-.nr PD 0
-.IP \ \ \(bu
-the \fBcd\fP command is disabled
-.IP \ \ \(bu
-the \fBSHELL\fP, \fBENV\fP and \fBPATH\fP parameters can't be changed
-.IP \ \ \(bu
-command names can't be specified with absolute or relative paths
-.IP \ \ \(bu
-the \fB\-p\fP option of the \fBcommand\fP built-in can't be used
-.IP \ \ \(bu
-redirections that create files can't be used (\fIi.e.\fP, \fB>\fP,
-\fB>|\fP, \fB>>\fP, \fB<>\fP)
-.nr PD \n(P2
-.PP
-A shell is \fBprivileged\fP if the \fB\-p\fP option is used or if
-the real user-id or group-id does not match the effective user-id
-or group-id (see \fIgetuid\fP(2), \fIgetgid\fP(2)).
-A privileged shell does not process $HOME/.profile nor the \fBENV\fP
-parameter (see below), instead the file /etc/suid_profile is processed.
-Clearing the privileged option causes the shell to set its effective
-user-id (group-id) to its real user-id (group-id).
-.PP
-If the basename of the name the shell is called with (\fIi.e.\fP, argv[0])
-starts with \fB\-\fP or if the \fB\-l\fP option is used, the shell is assumed
-to be a login shell and the shell reads and executes the contents of
-\fB/etc/profile\fP and \fB$HOME/.profile\fP if they exist and are readable.
-.PP
-If the \fBENV\fP parameter is set when the shell starts (or, in the
-case of login shells, after any profiles are processed), its value
-is subjected to parameter, command, arithmetic and tilde substitution and
-the resulting file (if any) is read and executed.
-If \fBENV\fP parameter is not set (and not null) and pdksh was compiled
-with the \fBDEFAULT_ENV\fP macro defined, the file named in that macro
-is included (after the above mentioned substitutions have been performed).
-.PP
-The exit status of the shell is 127 if the command file specified
-on the command line could not be opened, or non-zero if a fatal syntax
-error occurred during the execution of a script.
-In the absence of fatal errors, the exit status is that of the last
-command executed, or zero, if no command is executed.
-.\"}}}
-.\"{{{ Command Syntax
-.SS "Command Syntax"
-.\"{{{ words and tokens
-The shell begins parsing its input by breaking it into \fIword\fPs.
-Words, which are sequences of characters, are delimited by unquoted
-\fIwhite-space\fP characters (space, tab and newline) or \fImeta-characters\fP
-(\fB<\fP, \fB>\fP, \fB|\fP, \fB;\fP, \fB&\fP, \fB(\fP and \fB)\fP).
-Aside from delimiting words, spaces and tabs are ignored, while
-newlines usually delimit commands.
-The meta-characters are used in building the following tokens:
-\fB<\fP, \fB<&\fP, \fB<<\fP, \fB>\fP, \fB>&\fP, \fB>>\fP, \fIetc.\fP are
-used to specify redirections (see Input/Output Redirection below);
-\fB|\fP is used to create pipelines;
-\fB;\fP is used to separate commands;
-\fB&\fP is used to create asynchronous pipelines;
-\fB&&\fP and \fB||\fP are used to specify conditional execution;
-\fB;;\fP is used in \fBcase\fP statements;
-and lastly,
-\fB(\fP .. \fB)\fP are used to create subshells.
-.PP
-White-space and meta-characters can be quoted individually using
-backslash (\fB\e\fP), or in groups using double (\fB"\fP) or single (\fB'\fP)
-quotes.
-Note that the following characters are also treated specially by the shell and
-must be quoted if they are to represent themselves:
-\fB\e\fP, \fB"\fP, \fB'\fP, \fB#\fP, \fB$\fP, \fB`\fP, \fB~\fP, \fB{\fP,
-\fB}\fP, \fB*\fP, \fB?\fP and \fB[\fP.
-The first three of these are the above mentioned quoting characters
-(see Quoting below);
-\fB#\fP, if used at the beginning of a word, introduces a comment \(em everything
-after the \fB#\fP up to the nearest newline is ignored;
-\fB$\fP is used to introduce parameter, command and arithmetic substitutions
-(see Substitution below);
-\fB`\fP introduces an old-style command substitution
-(see Substitution below);
-\fB~\fP begins a directory expansion (see Tilde Expansion below);
-\fB{\fP and \fB}\fP delimit \fIcsh\fP(1) style alternations
-(see Brace Expansion below);
-and, finally, \fB*\fP, \fB?\fP and \fB[\fP are used in file name generation
-(see File Name Patterns below).
-.\"}}}
-.\"{{{ simple-command
-.PP
-As words and tokens are parsed, the shell builds commands, of which
-there are two basic types: \fIsimple-commands\fP, typically programs
-that are executed, and \fIcompound-commands\fP, such as \fBfor\fP and
-\fBif\fP statements, grouping constructs and function definitions.
-.PP
-A simple-command consists of some combination of parameter assignments (see
-Parameters below), input/output redirections (see Input/Output Redirections
-below), and command words; the only restriction is that parameter assignments
-come before any command words.
-The command words, if any, define the command that is to be executed and its
-arguments.
-The command may be a shell built-in command, a function or an \fIexternal
-command\fP, \fIi.e.\fP, a separate executable file that is located using the
-\fBPATH\fP parameter (see Command Execution below).
-Note that all command constructs have an \fIexit status\fP: for external
-commands, this is related to the status returned by \fIwait\fP(2) (if the
-command could not be found, the exit status is 127, if it could not be
-executed, the exit status is 126);
-the exit status of other command constructs (built-in commands, functions,
-compound-commands, pipelines, lists, \fIetc.\fP) are all well defined and are
-described where the construct is described.
-The exit status of a command consisting only of parameter assignments is that
-of the last command substitution performed during the parameter assignment
-or zero if there were no command substitutions.
-.\"}}}
-.\"{{{ pipeline
-.PP
-Commands can be chained together using the \fB|\fP token to
-form \fIpipelines\fP, in which the standard output of each command but
-the last is piped (see \fIpipe\fP(2)) to the standard input of the following
-command.
-The exit status of a pipeline is that of its last command.
-A pipeline may be prefixed by the \fB!\fP reserved word which
-causes the exit status of the pipeline to be logically
-complemented: if the original status was 0 the complemented status will
-be 1, and if the original status was not 0, then the complemented
-status will be 0.
-.\"}}}
-.\"{{{ lists
-.PP
-\fILists\fP of commands can be created by separating pipelines by
-any of the following tokens: \fB&&\fP, \fB||\fP, \fB&\fP, \fB|&\fP and \fB;\fP.
-The first two are for conditional execution: \fIcmd1\fP \fB&&\fP \fIcmd2\fP
-executes \fIcmd2\fP only if the exit status of \fIcmd1\fP is zero;
-\fB||\fP is the opposite \(em \fIcmd2\fP is executed only if the exit status
-of \fIcmd1\fP is non-zero.
-\fB&&\fP and \fB||\fP have equal precedence which is higher than that of
-\fB&\fP, \fB|&\fP and \fB;\fP, which also have equal precedence.
-The \fB&\fP token causes the preceding command to be executed asynchronously,
-that is, the shell starts the command, but does not wait for it to complete
-(the shell does keep track of the status of asynchronous commands \(em see
-Job Control below).
-When an asynchronous command is started when job control is disabled
-(\fIi.e.\fP, in most scripts), the command is started with signals INT
-and QUIT ignored and with input redirected from /dev/null
-(however, redirections specified in the asynchronous command have precedence).
-Note that a command must follow the \fB&&\fP and \fB||\fP operators, while
-a command need not follow \fB&\fP, \fB|&\fP and \fB;\fP.
-The exit status of a list is that of the last command executed, with the
-exception of asynchronous lists, for which the exit status is 0.
-.\"}}}
-.\"{{{ compound-commands
-.PP
-Compound commands are created using the following reserved words \(em these
-words are only recognized if they are unquoted and if they are used as
-the first word of a command (\fIi.e.\fP, they can't be preceded by parameter
-assignments or redirections):
-.TS
-center;
-lfB lfB lfB lfB lfB .
-case else function then !
-do esac if time [[
-done fi in until {
-elif for select while }
-.TE
-\fBNote:\fP Some shells (but not this one) execute control structure commands
-in a subshell when one or more of their file descriptors are redirected, so
-any environment changes inside them may fail.
-To be portable, the \fBexec\fP statement should be used instead to redirect
-file descriptors before the control structure.
-.PP
-In the following compound command descriptions, command lists (denoted as
-\fIlist\fP) that are followed by reserved words must end with a
-semi-colon, a newline or a (syntactically correct) reserved word.
-For example,
-.RS
-\fB{ echo foo; echo bar; }\fP
-.br
-\fB{ echo foo; echo bar<newline>}\fP
-.br
-\fB{ { echo foo; echo bar; } }\fP
-.RE
-are all valid, but
-.RS
-\fB{ echo foo; echo bar }\fP
-.RE
-is not.
-.\"{{{ ( list )
-.IP "\fB(\fP \fIlist\fP \fB)\fP"
-Execute \fIlist\fP in a subshell. There is no implicit way to pass
-environment changes from a subshell back to its parent.
-.\"}}}
-.\"{{{ { list }
-.IP "\fB{\fP \fIlist\fP \fB}\fP"
-Compound construct; \fIlist\fP is executed, but not in a subshell.
-Note that \fB{\fP and \fB}\fP are reserved words, not meta-characters.
-.\"}}}
-.\"{{{ case word in [ [ ( ] pattern [ | pattern ] ... ) list ;; ] ... esac
-.IP "\fBcase\fP \fIword\fP \fBin\fP [ [\fB(\fP] \fIpattern\fP [\fB|\fP \fIpattern\fP] ... \fB)\fP \fIlist\fP \fB;;\fP ] ... \fBesac\fP"
-The \fBcase\fP statement attempts to match \fIword\fP against the specified
-\fIpattern\fPs; the \fIlist\fP associated with the first successfully matched
-pattern is executed. Patterns used in \fBcase\fP statements are the same as
-those used for file name patterns except that the restrictions regarding
-\fB\&.\fP and \fB/\fP are dropped. Note that any unquoted space before and
-after a pattern is stripped; any space with a pattern must be quoted. Both the
-word and the patterns are subject to parameter, command, and arithmetic
-substitution as well as tilde substitution.
-For historical reasons, open and close braces may be used instead
-of \fBin\fP and \fBesac\fP (\fIe.g.\fP, \fBcase $foo { *) echo bar; }\fP).
-The exit status of a \fBcase\fP statement is that of the executed \fIlist\fP;
-if no \fIlist\fP is executed, the exit status is zero.
-.\"}}}
-.\"{{{ for name [ in word ... term ] do list done
-.IP "\fBfor\fP \fIname\fP [ \fBin\fP \fIword\fP ... \fIterm\fP ] \fBdo\fP \fIlist\fP \fBdone\fP"
-where \fIterm\fP is either a newline or a \fB;\fP.
-For each \fIword\fP in the specified word list, the parameter \fIname\fP is
-set to the word and \fIlist\fP is executed. If \fBin\fP is not used to
-specify a word list, the positional parameters (\fB"$1"\fP, \fB"$2"\fP,
-\fIetc.\fP) are used instead.
-For historical reasons, open and close braces may be used instead
-of \fBdo\fP and \fBdone\fP (\fIe.g.\fP, \fBfor i; { echo $i; }\fP).
-The exit status of a \fBfor\fP statement is the last exit status
-of \fIlist\fP; if \fIlist\fP is never executed, the exit status is zero.
-.\"}}}
-.\"{{{ if list then list [ elif list then list ] ... [ else list ] fi
-.IP "\fBif\fP \fIlist\fP \fBthen\fP \fIlist\fP [\fBelif\fP \fIlist\fP \fBthen\fP \fIlist\fP] ... [\fBelse\fP \fIlist\fP] \fBfi\fP"
-If the exit status of the first \fIlist\fP is zero, the second \fIlist\fP
-is executed; otherwise the \fIlist\fP following the \fBelif\fP, if any, is
-executed with similar consequences. If all the lists following the \fBif\fP
-and \fBelif\fPs fail (\fIi.e.\fP, exit with non-zero status), the \fIlist\fP
-following the \fBelse\fP is executed.
-The exit status of an \fBif\fP statement is that
-of non-conditional \fIlist\fP that is executed; if no non-conditional
-\fIlist\fP is executed, the exit status is zero.
-.\"}}}
-.\"{{{ select name [ in word ... ] do list done
-.\"}}}
-.\"{{{ until list do list done
-.IP "\fBuntil\fP \fIlist\fP \fBdo\fP \fIlist\fP \fBdone\fP"
-This works like \fBwhile\fP, except that the body is executed only while the
-exit status of the first \fIlist\fP is non-zero.
-.\"}}}
-.\"{{{ while list do list done
-.IP "\fBwhile\fP \fIlist\fP \fBdo\fP \fIlist\fP \fBdone\fP"
-A \fBwhile\fP is a prechecked loop. Its body is executed as often
-as the exit status of the first \fIlist\fP is zero.
-The exit status of a \fBwhile\fP statement is the last exit status
-of the \fIlist\fP in the body of the loop; if the body is not executed,
-the exit status is zero.
-.\"}}}
-.\"{{{ function name { list }
-.IP "\fBfunction\fP \fIname\fP \fB{\fP \fIlist\fP \fB}\fP"
-Defines the function \fIname\fP.
-See Functions below.
-Note that redirections specified after a function definition are
-performed whenever the function is executed, not when the function
-definition is executed.
-.\"}}}
-.\"{{{ name () command
-.IP "\fIname\fP \fB()\fP \fIcommand\fP"
-Mostly the same as \fBfunction\fP.
-See Functions below.
-.\"}}}
-.\"{{{ (( expression ))
-.\"}}}
-.\"{{{ [[ expression ]]
-.\"}}}
-.\"}}}
-.\"}}}
-.\"{{{ Quoting
-.SS Quoting
-Quoting is used to prevent the shell from treating characters or words
-specially.
-There are three methods of quoting: First, \fB\e\fP quotes
-the following character, unless it is at the end of a line, in which
-case both the \fB\e\fP and the newline are stripped.
-Second, a single quote (\fB'\fP) quotes everything up to the next single
-quote (this may span lines).
-Third, a double quote (\fB"\fP) quotes all characters,
-except \fB$\fP, \fB`\fP and \fB\e\fP, up to the next unquoted double quote.
-\fB$\fP and \fB`\fP inside double quotes have their usual meaning (\fIi.e.\fP,
-parameter, command or arithmetic substitution) except no field splitting
-is carried out on the results of double-quoted substitutions.
-If a \fB\e\fP inside a double-quoted string is followed by \fB\e\fP, \fB$\fP,
-\fB`\fP or \fB"\fP, it is replaced by the second character; if it is
-followed by a newline, both the \fB\e\fP and the newline are stripped;
-otherwise, both the \fB\e\fP and the character following are unchanged.
-.PP
-Note: see POSIX Mode below for a special rule regarding sequences
-of the form \fB"\fP...\fB`\fP...\fB\e"\fP...\fB`\fP..\fB"\fP.
-.\"}}}
-.\"{{{ Aliases
-.SS "Aliases"
-There are two types of aliases: normal command aliases and tracked
-aliases. Command aliases are normally used as a short hand for a long
-or often used command. The shell expands command aliases (\fIi.e.\fP,
-substitutes the alias name for its value) when it reads the first word
-of a command. An expanded alias is re-processed to check for more
-aliases. If a command alias ends in a space or tab, the following word
-is also checked for alias expansion. The alias expansion process stops
-when a word that is not an alias is found, when a quoted word is found
-or when an alias word that is currently being expanded is found.
-.PP
-The following command aliases are defined automatically by the shell:
-.ft B
-.RS
-hash='alias \-t'
-.br
-type='whence \-v'
-.RE
-.ft P
-.PP
-Tracked aliases allow the shell to remember where it found a particular
-command. The first time the shell does a path search for a command that
-is marked as a tracked alias, it saves the full path of the command.
-The next time the command is executed, the shell checks the saved path
-to see that it is still valid, and if so, avoids repeating the path
-search. Tracked aliases can be listed and created using \fBalias
-\-t\fP. Note that changing the \fBPATH\fP parameter clears the saved
-paths for all tracked aliases. If the \fBtrackall\fP option is set (\fIi.e.\fP,
-\fBset \-o trackall\fP or \fBset \-h\fP), the shell tracks all
-commands. This option is set automatically for non-interactive shells.
-For interactive shells, only the following commands are automatically
-tracked: \fBcat\fP, \fBcc\fP, \fBchmod\fP, \fBcp\fP, \fBdate\fP, \fBed\fP,
-\fBemacs\fP, \fBgrep\fP, \fBls\fP, \fBmail\fP, \fBmake\fP, \fBmv\fP,
-\fBpr\fP, \fBrm\fP, \fBsed\fP, \fBsh\fP, \fBvi\fP and \fBwho\fP.
-.\"}}}
-.\"{{{ Substitution
-.SS "Substitution"
-The first step the shell takes in executing a simple-command is to
-perform substitutions on the words of the command.
-There are three kinds of substitution: parameter, command and arithmetic.
-Parameter substitutions, which are described in detail in the next section,
-take the form \fB$name\fP or \fB${\fP...\fB}\fP; command substitutions take
-the form \fB$(\fP\fIcommand\fP\fB)\fP or \fB`\fP\fIcommand\fP\fB`\fP;
-and arithmetic substitutions take the form \fB$((\fP\fIexpression\fP\fB))\fP.
-.PP
-If a substitution appears outside of double quotes, the results of the
-substitution are generally subject to word or field splitting according to
-the current value of the \fBIFS\fP parameter.
-The \fBIFS\fP parameter specifies a list of characters which
-are used to break a string up into several words;
-any characters from the set space, tab and newline that appear in the
-IFS characters are called \fIIFS white space\fP.
-Sequences of one or more IFS white space characters, in combination with
-zero or one non-IFS white space characters delimit a field.
-As a special case, leading and trailing IFS white space is stripped (\fIi.e.\fP,
-no leading or trailing empty field is created by it); leading or trailing
-non-IFS white space does create an empty field.
-.PP
-Example: if \fBIFS\fP is set to `<space>:', and VAR is set to
-`<space>A<space>:<space><space>B::D', the substitution for $VAR results
-in four fields: `A', `B', `' and `D'.
-Note that if the \fBIFS\fP parameter is set to the null string, no
-field splitting is done; if the parameter is unset, the default value
-of space, tab and newline is used.
-.PP
-Also, note that the field splitting applies only to immediate result of
-the substitution. Using the previous example, the substitution for $VAR:E
-results in the fields: `A', `B', `' and `D:E', not `A', `B', `', `D' and `E'.
-This behavior is POSIX compliant, but incompatible with some other shell
-implementations which do field splitting on the word which contained the
-substitution or use \fBIFS\fP\ as a general whitespace delimiter.
-.PP
-The results of substitution are, unless otherwise specified, also subject
-to brace expansion and file name expansion (see the relevant sections
-below).
-.PP
-A command substitution is replaced by the output generated by the specified
-command, which is run in a subshell.
-For \fB$(\fP\fIcommand\fP\fB)\fP substitutions, normal quoting rules
-are used when \fIcommand\fP is parsed, however, for the
-\fB`\fP\fIcommand\fP\fB`\fP form, a \fB\e\fP followed by any of
-\fB$\fP, \fB`\fP or \fB\e\fP is stripped (a \fB\e\fP followed by any other
-character is unchanged).
-As a special case in command substitutions, a command of the form
-\fB<\fP \fIfile\fP is interpreted to mean substitute the contents
-of \fIfile\fP ($(< foo) has the same effect as $(cat foo), but it
-is carried out more efficiently because no process is started).
-.br
-.\"todo: fix this( $(..) parenthesis counting).
-NOTE: \fB$(\fP\fIcommand\fP\fB)\fP expressions are currently parsed by
-finding the matching parenthesis, regardless of quoting. This will hopefully
-be fixed soon.
-.PP
-Arithmetic substitutions are replaced by the value of the specified
-expression.
-For example, the command \fBecho $((2+3*4))\fP prints 14.
-See Arithmetic Expressions for a description of an \fIexpression\fP.
-.\"}}}
-.\"{{{ Parameters
-.SS "Parameters"
-Parameters are shell variables; they can be assigned values and
-their values can be accessed using a parameter substitution.
-A parameter name is either one of the special single punctuation or digit
-character parameters described below, or a letter followed by zero or more
-letters or digits (`_' counts as a letter).
-Parameter substitutions take the form \fB$\fP\fIname\fP or
-\fB${\fP\fIname\fP\fB}\fP, where \fIname\fP is a parameter name.
-If substitution is performed on a parameter that is not set, a null
-string is substituted unless the \fBnounset\fP option (\fBset \-o nounset\fP
-or \fBset \-u\fP) is set, in which case an error occurs.
-.PP
-.\"{{{ parameter assignment
-Parameters can be assigned values in a number of ways.
-First, the shell implicitly sets some parameters like \fB#\fP, \fBPWD\fP,
-etc.; this is the only way the special single character parameters are
-set.
-Second, parameters are imported from the shell's environment at startup.
-Third, parameters can be assigned values on the command line, for example,
-`\fBFOO=bar\fP' sets the parameter FOO to bar; multiple parameter
-assignments can be given on a single command line and they can
-be followed by a simple-command, in which case the assignments are
-in effect only for the duration of the command (such assignments are
-also exported, see below for implications of this).
-Note that both the parameter name and the \fB=\fP must be unquoted for
-the shell to recognize a parameter assignment.
-The fourth way of setting a parameter is with the \fBexport\fP, \fBreadonly\fP
-and \fBtypeset\fP commands; see their descriptions in the Command Execution
-section.
-Fifth, \fBfor\fP and \fBselect\fP loops set parameters as well as
-the \fBgetopts\fP, \fBread\fP and \fBset \-A\fP commands.
-Lastly, parameters can be assigned values using assignment operators
-inside arithmetic expressions (see Arithmetic Expressions below) or
-using the \fB${\fP\fIname\fP\fB=\fP\fIvalue\fP\fB}\fP form
-of parameter substitution (see below).
-.\"}}}
-.PP
-.\"{{{ environment
-Parameters with the export attribute (set using the \fBexport\fP or
-\fBtypeset \-x\fP commands, or by parameter assignments followed by simple
-commands) are put in the environment (see \fIenviron\fP(5)) of commands
-run by the shell as \fIname\fP\fB=\fP\fIvalue\fP pairs.
-The order in which parameters appear in the environment of a command
-is unspecified.
-When the shell starts up, it extracts parameters and their values from its
-environment and automatically sets the export attribute for those parameters.
-.\"}}}
-.\"{{{ ${name[:][-+=?]word}
-.PP
-Modifiers can be applied to the \fB${\fP\fIname\fP\fB}\fP form of parameter
-substitution:
-.IP \fB${\fP\fIname\fP\fB:-\fP\fIword\fP\fB}\fP
-if \fIname\fP is set and not null, it is substituted, otherwise \fIword\fP is
-substituted.
-.IP \fB${\fP\fIname\fP\fB:+\fP\fIword\fP\fB}\fP
-if \fIname\fP is set and not null, \fIword\fP is substituted, otherwise nothing is substituted.
-.IP \fB${\fP\fIname\fP\fB:=\fP\fIword\fP\fB}\fP
-if \fIname\fP is set and not null, it is substituted, otherwise it is
-assigned \fIword\fP and the resulting value of \fIname\fP is substituted.
-.IP \fB${\fP\fIname\fP\fB:?\fP\fIword\fP\fB}\fP
-if \fIname\fP is set and not null, it is substituted, otherwise \fIword\fP
-is printed on standard error (preceded by \fIname\fP:) and an error occurs
-(normally causing termination of a shell script, function or \&.-script).
-If word is omitted the string `parameter null or not set' is used instead.
-.PP
-In the above modifiers, the \fB:\fP can be omitted, in which case the
-conditions only depend on \fIname\fP being set (as opposed to set and
-not null).
-If \fIword\fP is needed, parameter, command, arithmetic and tilde substitution
-are performed on it; if \fIword\fP is not needed, it is not evaluated.
-.\"}}}
-.PP
-The following forms of parameter substitution can also be used:
-.\"{{{ ${#name}
-.IP \fB${#\fP\fIname\fP\fB}\fP
-The number of positional parameters if \fIname\fP is \fB*\fP, \fB@\fP or
-is not specified,
-or the length of the string value of parameter \fIname\fP.
-.\"}}}
-.\"{{{ ${#name[*]}, ${#name[@]}
-.IP "\fB${#\fP\fIname\fP\fB[*]}\fP, \fB${#\fP\fIname\fP\fB[@]}\fP"
-The number of elements in the array \fIname\fP.
-.\"}}}
-.\"{{{ ${name#pattern}, ${name##pattern}
-.IP "\fB${\fP\fIname\fP\fB#\fP\fIpattern\fP\fB}\fP, \fB${\fP\fIname\fP\fB##\fP\fIpattern\fP\fB}\fP"
-If \fIpattern\fP matches the beginning of the value of parameter \fIname\fP,
-the matched text is deleted from the result of substitution. A single
-\fB#\fP results in the shortest match, two \fB#\fP's results in the
-longest match.
-.\"}}}
-.\"{{{ ${name%pattern}, ${name%%pattern}
-.IP "\fB${\fP\fIname\fP\fB%\fP\fIpattern\fP\fB}\fP, \fB${\fP\fIname\fP\fB%%\fP\fIpattern\fP\fB}\fP"
-Like \fB${\fP..\fB#\fP..\fB}\fP substitution, but it deletes from the end of the
-value.
-.\"}}}
-.\"{{{ special shell parameters
-.PP
-The following special parameters are implicitly set by the shell and cannot be
-set directly using assignments:
-.\"{{{ !
-.IP \fB!\fP
-Process id of the last background process started. If no background
-processes have been started, the parameter is not set.
-.\"}}}
-.\"{{{ #
-.IP \fB#\fP
-The number of positional parameters (\fIi.e.\fP, \fB$1\fP, \fB$2\fP,
-\fIetc.\fP).
-.\"}}}
-.\"{{{ $
-.IP \fB$\fP
-The process ID of the shell, or the PID of the original shell if
-it is a subshell.
-.\"}}}
-.\"{{{ -
-.IP \fB\-\fP
-The concatenation of the current single letter options
-(see \fBset\fP command below for list of options).
-.\"}}}
-.\"{{{ ?
-.IP \fB?\fP
-The exit status of the last non-asynchronous command executed.
-If the last command was killed by a signal, \fB$?\fP is set to 128 plus
-the signal number.
-.\"}}}
-.\"{{{ 0
-.IP "\fB0\fP"
-The name the shell was invoked with (\fIi.e.\fP, \fBargv[0]\fP), or the
-\fBcommand-name\fP if it was invoked with the \fB\-c\fP option and the
-\fBcommand-name\fP was supplied, or the \fIfile\fP argument, if it was
-supplied.
-If the \fBposix\fP option is not set, \fB$0\fP is the name of the current
-function or script.
-.\"}}}
-.\"{{{ 1-9
-.IP "\fB1\fP ... \fB9\fP"
-The first nine positional parameters that were supplied to the shell,
-function or \fB.\fP-script.
-Further positional parameters may be accessed using
-\fB${\fP\fInumber\fP\fB}\fP.
-.\"}}}
-.\"{{{ *
-.IP \fB*\fP
-All positional parameters (except parameter 0),
-\fIi.e.\fP, \fB$1 $2 $3\fP....
-If used outside of double quotes, parameters are separate words
-(which are subjected to word splitting); if used within double quotes,
-parameters are separated by the first character of the \fBIFS\fP parameter
-(or the empty string if \fBIFS\fP is null).
-.\"}}}
-.\"{{{ @
-.IP \fB@\fP
-Same as \fB$*\fP, unless it is used inside double quotes, in which case
-a separate word is generated for each positional parameter \- if there
-are no positional parameters, no word is generated ("$@" can be used
-to access arguments, verbatim, without loosing null arguments or
-splitting arguments with spaces).
-.\"}}}
-.\"}}}
-.\"{{{ general shell parameters
-.PP
-The following parameters are set and/or used by the shell:
-.\"{{{ CDPATH
-.IP \fBCDPATH\fP
-Search path for the \fBcd\fP built-in command. Works the same way as
-\fBPATH\fP for those directories not beginning with \fB/\fP in \fBcd\fP
-commands.
-Note that if CDPATH is set and does not contain \fB.\fP nor an empty path,
-the current directory is not searched.
-.\"}}}
-.\"{{{ COLUMNS
-.IP \fBCOLUMNS\fP
-Set to the number of columns on the terminal or window.
-Currently set to the \fBcols\fP value as reported by \fIstty\fP(1) if that
-value is non-zero.
-This parameter is used by the interactive line editing modes, and by
-\fBselect\fP, \fBset \-o\fP and \fBkill \-l\fP commands
-to format information in columns.
-.\"}}}
-.\"{{{ EDITOR
-.\"}}}
-.\"{{{ ENV
-.IP \fBENV\fP
-If this parameter is found to be set after any profile files are
-executed, the expanded value is used as a shell start-up file. It
-typically contains function and alias definitions.
-.\"}}}
-.\"{{{ ERRNO
-.IP \fBERRNO\fP
-Integer value of the shell's errno variable \(em indicates the reason
-the last system call failed.
-.\" todo: ERRNO variable
-.sp
-Not implemented yet.
-.\"}}}
-.\"{{{ EXECSHELL
-.IP \fBEXECSHELL\fP
-If set, this parameter is assumed to contain the shell that is to be
-used to execute commands that \fIexecve\fP(2) fails to execute and
-which do not start with a `\fB#!\fP \fIshell\fP' sequence.
-.\"}}}
-.\"{{{ FCEDIT
-.IP \fBFCEDIT\fP
-The editor used by the \fBfc\fP command (see below).
-.\"}}}
-.\"{{{ FPATH
-.IP \fBFPATH\fP
-Like \fBPATH\fP, but used when an undefined function is executed to locate
-the file defining the function.
-It is also searched when a command can't be found using \fBPATH\fP.
-See Functions below for more information.
-.\"}}}
-.\"{{{ HISTFILE
-.\"}}}
-.\"{{{ HISTSIZE
-.\"}}}
-.\"{{{ HOME
-.IP \fBHOME\fP
-The default directory for the \fBcd\fP command and the value
-substituted for an unqualified \fB~\fP (see Tilde Expansion below).
-.\"}}}
-.\"{{{ IFS
-.IP \fBIFS\fP
-Internal field separator, used during substitution and by the \fBread\fP
-command, to split values into distinct arguments; normally set to
-space, tab and newline. See Substitution above for details.
-.br
-\fBNote:\fP this parameter is not imported from the environment
-when the shell is started.
-.\"}}}
-.\"{{{ KSH_VERSION
-.\"}}}
-.\"{{{ SH_VERSION
-.IP \fBSH_VERSION\fP
-The version of shell and the date the version was created (readonly).
-.\"}}}
-.\"{{{ LINENO
-.IP \fBLINENO\fP
-The line number of the function or shell script that is currently being
-executed.
-.\" todo: LINENO variable
-.sp
-Not implemented yet.
-.\"}}}
-.\"{{{ LINES
-.IP \fBLINES\fP
-Set to the number of lines on the terminal or window.
-.\"Currently set to the \fBrows\fP value as reported by \fIstty\fP(1) if that
-.\"value is non-zero.
-.\" todo: LINES variable
-.sp
-Not implemented yet.
-.\"}}}
-.\"{{{ MAIL
-.\"}}}
-.\"{{{ MAILCHECK
-.\"}}}
-.\"{{{ MAILPATH
-.\"}}}
-.\"{{{ OLDPWD
-.IP \fBOLDPWD\fP
-The previous working directory.
-Unset if \fBcd\fP has not successfully changed directories since the
-shell started, or if the shell doesn't know where it is.
-.\"}}}
-.\"{{{ OPTARG
-.IP \fBOPTARG\fP
-When using \fBgetopts\fP, it contains the argument for a parsed option,
-if it requires one.
-.\"}}}
-.\"{{{ OPTIND
-.IP \fBOPTIND\fP
-The index of the last argument processed when using \fBgetopts\fP.
-Assigning 1 to this parameter causes \fBgetopts\fP to
-process arguments from the beginning the next time it is invoked.
-.\"}}}
-.\"{{{ PATH
-.IP \fBPATH\fP
-A colon separated list of directories that are searched when looking
-for commands and \fB.\fP'd files.
-An empty string resulting from a leading or trailing colon, or two adjacent
-colons is treated as a `.', the current directory.
-.\"}}}
-.\"{{{ POSIXLY_CORRECT
-.IP \fBPOSIXLY_CORRECT\fP
-If set, this parameter causes the \fBposix\fP option to be enabled.
-See POSIX Mode below.
-.\"}}}
-.\"{{{ PPID
-.IP \fBPPID\fP
-The process ID of the shell's parent (readonly).
-.\"}}}
-.\"{{{ PS1
-.IP \fBPS1\fP
-\fBPS1\fP is the primary prompt for interactive shells.
-The prompt is printed verbatim (\fIi.e.\fP, no substitutions are done).
-Default is `\fB$\ \fP' for non-root users, `\fB#\ \fP' for root..
-.\"}}}
-.\"{{{ PS2
-.IP \fBPS2\fP
-Secondary prompt string, by default `\fB>\fP ', used when more input is
-needed to complete a command.
-.\"}}}
-.\"{{{ PS3
-.\"}}}
-.\"{{{ PS4
-.IP \fBPS4\fP
-Used to prefix commands that are printed during execution tracing
-(see \fBset \-x\fP command below).
-The prompt is printed verbatim (\fIi.e.\fP, no substitutions are done).
-Default is `\fB+\ \fP'.
-.\"}}}
-.\"{{{ PWD
-.IP \fBPWD\fP
-The current working directory. Maybe unset or null if shell doesn't
-know where it is.
-.\"}}}
-.\"{{{ RANDOM
-.\"}}}
-.\"{{{ REPLY
-.IP \fBREPLY\fP
-Default parameter for the \fBread\fP command if no names are given.
-Also used in \fBselect\fP loops to store the value that is read from
-standard input.
-.\"}}}
-.\"{{{ SECONDS
-.\"}}}
-.\"{{{ TMOUT
-.\"}}}
-.\"{{{ TMPDIR
-.IP \fBTMPDIR\fP
-The directory shell temporary files are created in. If this parameter
-is not set, or does not contain the absolute path of a writable
-directory, temporary files are created in \fB/tmp\fP.
-.\"}}}
-.\"{{{ VISUAL
-.\"}}}
-.\"}}}
-.\"}}}
-.\"{{{ Tilde Expansion
-.SS "Tilde Expansion"
-Tilde expansion, which is done in parallel with parameter substitution,
-is done on words starting with an unquoted \fB~\fP. The characters
-following the tilde, up to the first \fB/\fP, if any, are assumed to be
-a login name. If the login name is empty, \fB+\fP or \fB\-\fP, the
-value of the \fBHOME\fP, \fBPWD\fP, or \fBOLDPWD\fP parameter is
-substituted, respectively. Otherwise, the password file is searched for
-the login name, and the tilde expression is substituted with the
-user's home directory. If the login name is not found in the password
-file or if any quoting or parameter substitution occurs in the login name,
-no substitution is performed.
-.PP
-In parameter assignments (those preceding a simple-command or those
-occurring in the arguments of \fBalias\fP, \fBexport\fP, \fBreadonly\fP,
-and \fBtypeset\fP), tilde expansion is done after any unquoted colon
-(\fB:\fP), and login names are also delimited by colons.
-.PP
-The home directory of previously expanded login names are cached and
-re-used. The \fBalias \-d\fP command may be used to list, change and
-add to this cache (\fIe.g.\fP, `alias \-d fac=/usr/local/facilities; cd
-~fac/bin').
-.\"}}}
-.\"{{{ Brace Expansion
-.\"}}}
-.\"{{{ File Name Patterns
-.SS "File Name Patterns"
-.PP
-A file name pattern is a word containing one or more unquoted \fB?\fP or
-\fB*\fP characters or \fB[\fP..\fB]\fP sequences. Once brace expansion has
-been performed, the shell replaces file name patterns with the sorted names
-of all the files that match the pattern (if no files match, the word is
-left unchanged). The pattern elements have the following meaning:
-.IP \fB?\fP
-matches any single character.
-.IP \fB*\fP
-matches any sequence of characters.
-.IP \fB[\fP..\fB]\fP
-matches any of the characters inside the brackets. Ranges of characters
-can be specified by separating two characters by a \fB\-\fP, \fIe.g.\fP,
-\fB[a0\-9]\fP matches the letter \fBa\fP or any digit.
-In order to represent itself, a
-\fB\-\fP must either be quoted or the first or last character in the character
-list. Similarly, a \fB]\fP must be quoted or the first character in the list
-if it is represent itself instead of the end of the list. Also, a \fB!\fP
-appearing at the start of the list has special meaning (see below), so to
-represent itself it must be quoted or appear later in the list.
-.IP \fB[!\fP..\fB]\fP
-like \fB[\fP..\fB]\fP, except it matches any character not inside the brackets.
-.PP
-Note that pdksh currently never matches \fB.\fP and \fB..\fP, but the original
-ksh, Bourne sh and bash do, so this may have to change (too bad).
-.PP
-Note that none of the above pattern elements match either a period (\fB.\fP)
-at the start of a file name or a slash (\fB/\fP), even if they are explicitly
-used in a \fB[\fP..\fB]\fP sequence; also, the names \fB.\fP and \fB..\fP
-are never matched, even by the pattern \fB.*\fP.
-.PP
-If the \fBmarkdirs\fP option is set, any directories that result from
-file name generation are marked with a trailing \fB/\fP.
-.PP
-.\" todo: implement this ([[:alpha:]], \fIetc.\fP)
-The POSIX character classes (\fIi.e.\fP,
-\fB[:\fP\fIclass-name\fP\fB:]\fP inside a \fB[\fP..\fB]\fP expression)
-are not yet implemented.
-.\"}}}
-.\"{{{ Input/Output Redirection
-.SS "Input/Output Redirection"
-When a command is executed, its standard input, standard output and
-standard error (file descriptors 0, 1 and 2, respectively) are normally
-inherited from the shell.
-Three exceptions to this are commands in pipelines, for which standard input
-and/or standard output are those set up by the pipeline, asynchronous commands
-created when job control is disabled, for which standard input is initially
-set to be from \fB/dev/null\fP, and commands for which any of the following
-redirections have been specified:
-.IP "\fB>\fP \fIfile\fP"
-standard output is redirected to \fIfile\fP. If \fIfile\fP does not exist,
-it is created; if it does exist, is a regular file and the \fBnoclobber\fP
-option is set, an error occurs, otherwise the file is truncated.
-Note that this means the command \fIcmd < foo > foo\fP will open
-\fIfoo\fP for reading and then truncate it when it opens it for writing,
-before \fIcmd\fP gets a chance to actually read \fIfoo\fP.
-.IP "\fB>|\fP \fIfile\fP"
-same as \fB>\fP, except the file is truncated, even if the \fBnoclobber\fP
-option is set.
-.IP "\fB>>\fP \fIfile\fP"
-same as \fB>\fP, except the file an existing file is appended to instead
-of being truncated. Also, the file is opened in append mode, so writes
-always go to the end of the file (see \fIopen\fP(2)).
-.IP "\fB<\fP \fIfile\fP"
-standard input is redirected from \fIfile\fP, which is opened for reading.
-.IP "\fB<>\fP \fIfile\fP"
-same as \fB<\fP, except the file is opened for reading and writing.
-.IP "\fB<<\fP \fImarker\fP"
-after reading the command line containing this kind of redirection (called a
-here document), the shell copies lines from the command source into a temporary
-file until a line matching \fImarker\fP is read.
-When the command is executed, standard input is redirected from the temporary
-file.
-If \fImarker\fP contains no quoted characters, the contents of the
-temporary file are processed as if enclosed in double quotes each time
-the command is executed, so parameter, command and arithmetic substitutions
-are performed, along with backslash (\fB\e\fP) escapes for
-\fB$\fP, \fB`\fP, \fB\e\fP and \fB\enewline\fP.
-If multiple here documents are used on the same command line, they are
-saved in order.
-.IP "\fB<<-\fP \fImarker\fP"
-same as \fB<<\fP, except leading tabs are stripped from lines in the
-here document.
-.IP "\fB<&\fP \fIfd\fP"
-standard input is duplicated from file descriptor \fIfd\fP.
-\fIfd\fP can be a single digit, indicating the number of an existing
-file descriptor, the letter \fBp\fP, indicating the file descriptor
-associated with the output of the current co-process, or
-the character \fB\-\fP, indicating standard input is to be closed.
-.IP "\fB>&\fP \fIfd\fP"
-same as \fB<&\fP, except the operation is done on standard output.
-.PP
-In any of the above redirections, the file descriptor that is redirected
-(\fIi.e.\fP, standard input or standard output) can be explicitly given by
-preceding the redirection with a single digit.
-Parameter, command and arithmetic substitutions, tilde substitutions and
-file name generation are all performed on the \fIfile\fP, \fImarker\fP and
-\fIfd\fP arguments of redirections.
-Note however, that the results of any file name generation are only used
-if a single file is matched; if multiple files match, the word with the
-unexpanded file name generation characters is used.
-Note that in restricted shells, redirections which can create files cannot
-be used.
-.PP
-For simple-commands, redirections may appear anywhere in the command, for
-compound-commands (\fBif\fP statements, \fIetc.\fP), any redirections must
-appear at the end.
-Redirections are processed after pipelines are created and in the order they
-are given, so
-.RS
-\fBcat /foo/bar 2>&1 > /dev/null | cat \-n\fP
-.RE
-will print an error with a line number prepended to it.
-.\"}}}
-.\"{{{ Arithmetic Expressions
-.SS "Arithmetic Expressions"
-Integer arithmetic expressions can be used
-inside \fB$((\fP..\fB))\fP expressions,
-inside array references (\fIe.g.\fP, \fIname\fP\fB[\fP\fIexpr\fP\fB]\fP),
-as numeric arguments to the \fBtest\fP command,
-and as the value of an assignment to an integer parameter.
-.PP
-Expression may contain alpha-numeric parameter identifiers, array
-references, and integer constants and may be combined with the
-following C operators (listed and grouped in increasing order of precedence).
-.TP
-Unary operators:
-\fB+ \- ! ~ ++ --\fP
-.TP
-Binary operators:
-\fB,\fP
-.br
-\fB= *= /= %= += \-= <<= >>= &= ^= |=\fP
-.br
-\fB||\fP
-.br
-\fB&&\fP
-.br
-\fB|\fP
-.br
-\fB^\fP
-.br
-\fB&\fP
-.br
-\fB== !=\fP
-.br
-\fB< <= >= >\fP
-.br
-\fB<< >>\fP
-.br
-\fB+ \-\fP
-.br
-\fB* / %\fP
-.TP
-Ternary operator:
-\fB?:\fP (precedence is immediately higher than assignment)
-.TP
-Grouping operators:
-\fB( )\fP
-.PP
-Integer constants may be specified with arbitrary bases using the notation
-\fIbase\fP\fB#\fP\fInumber\fP, where \fIbase\fP is a decimal integer specifying
-the base, and \fInumber\fP is a number in the specified base.
-.LP
-The operators are evaluated as follows:
-.RS
-.IP "unary \fB+\fP"
-result is the argument (included for completeness).
-.IP "unary \fB\-\fP"
-negation.
-.IP "\fB!\fP"
-logical not; the result is 1 if argument is zero, 0 if not.
-.IP "\fB~\fP"
-arithmetic (bit-wise) not.
-.IP "\fB++\fP"
-increment; must be applied to a parameter (not a literal or other
-expression) - the parameter is incremented by 1.
-When used as a prefix operator, the result is the incremented value of
-the parameter, when used as a postfix operator, the result is the
-original value of the parameter.
-.IP "\fB++\fP"
-similar to \fB++\fP, except the paramter is decremented by 1.
-.IP "\fB,\fP"
-seperates two arithmetic expressions; the left hand side is evaluated first,
-then the right. The result is value of the expression on the right hand side.
-.IP "\fB=\fP"
-assignment; variable on the left is set to the value on the right.
-.IP "\fB*= /= %= += \-= <<= >>= &= ^= |=\fP"
-assignment operators; \fI<var> <op>\fP\fB=\fP \fI<expr>\fP is the same as
-\fI<var>\fP \fB=\fP \fI<var> <op>\fP \fB(\fP \fI<expr>\fP \fB)\fP.
-.IP "\fB||\fP"
-logical or; the result is 1 if either argument is non-zero, 0 if not.
-The right argument is evaluated only if the left argument is zero.
-.IP "\fB&&\fP"
-logical and; the result is 1 if both arguments are non-zero, 0 if not.
-The right argument is evaluated only if the left argument is non-zero.
-.IP "\fB|\fP"
-arithmetic (bit-wise) or.
-.IP "\fB^\fP"
-arithmetic (bit-wise) exclusive-or.
-.IP "\fB&\fP"
-arithmetic (bit-wise) and.
-.IP "\fB==\fP"
-equal; the result is 1 if both arguments are equal, 0 if not.
-.IP "\fB!=\fP"
-not equal; the result is 0 if both arguments are equal, 1 if not.
-.IP "\fB<\fP"
-less than; the result is 1 if the left argument is less than the right,
-0 if not.
-.IP "\fB<= >= >\fP"
-less than or equal, greater than or equal, greater than. See <.
-.IP "\fB<< >>\fP"
-shift left (right); the result is the left argument with its bits shifted
-left (right) by the amount given in the right argument.
-.IP "\fB+ - * /\fP"
-addition, subtraction, multiplication, and division.
-.IP "\fB%\fP"
-remainder; the result is the remainder of the division of the left argument
-by the right. The sign of the result is unspecified if either argument
-is negative.
-.IP "\fI<arg1>\fP \fB?\fP \fI<arg2>\fP \fB:\fP \fI<arg3>\fP"
-if \fI<arg1>\fP is non-zero, the result is \fI<arg2>\fP,
-otherwise \fI<arg3>\fP.
-.RE
-.\"}}}
-.\"{{{ Co-Processes
-.\"}}}
-.\"{{{ Functions
-.SS "Functions"
-Functions are defined using either Korn shell \fBfunction\fP \fIname\fP
-syntax or the Bourne/POSIX shell \fIname\fP\fB()\fP syntax
-(see below for the difference between the two forms).
-Functions are like \fB.\fP-scripts in that they are executed in
-the current environment, however, unlike \fB.\fP-scripts, shell arguments
-(\fIi.e.\fP, positional parameters, \fB$1\fP, \fIetc.\fP) are never visible
-inside them.
-When the shell is determining the location of a command, functions are
-searched after special built-in commands, and before regular and non-regular
-built-ins, and before the \fBPATH\fP is searched.
-.PP
-An existing function may be deleted using \fBunset \-f\fP \fIfunction-name\fP.
-A list of functions can be obtained using \fBtypeset +f\fP and the
-function definitions can be listed using \fBtypeset \-f\fP.
-\fBautoload\fP (which is an alias for \fBtypeset \-fu\fP) may be used to
-create undefined functions; when an undefined function is executed, the
-shell searches the path specified in the \fBFPATH\fP parameter for a file
-with the same name as the function, which, if found is read and executed.
-If after executing the file, the named function is found to be defined, the
-function is executed, otherwise, the normal command search is continued
-(\fIi.e.\fP, the shell searches the regular built-in command table
-and \fBPATH\fP).
-Note that if a command is not found using \fBPATH\fP, an attempt is
-made to autoload a function using \fBFPATH\fP (this is an undocumented
-feature of the original Korn shell).
-.PP
-Functions can have two attributes, trace and export, which can be set
-with \fBtypeset \-ft\fP and \fBtypeset \-fx\fP, respectively.
-When a traced function is executed, the shell's \fBxtrace\fP option is turned
-on for the functions duration, otherwise the \fBxtrace\fP option is turned off.
-The export attribute of functions is currently not used. In the original
-Korn shell, exported functions are visible to shell scripts that are executed.
-.PP
-Since functions are executed in the current shell environment, parameter
-assignments made inside functions are visible after the function completes.
-If this is not the desired effect, the \fBtypeset\fP command can be used
-inside a function to create a local parameter.
-Note that special parameters (\fIe.g.\fP, \fB$$\fP, \fB$!\fP) can't be
-scoped in this way.
-.PP
-The exit status of a function is that of the last command executed in
-the function.
-A function can be made to finish immediately using the \fBreturn\fP command;
-this may also be used to explicitly specify the exit status.
-.PP
-Functions defined with the \fBfunction\fP reserved word are
-treated differently in the following ways from functions defined with
-the \fB()\fP notation:
-.nr P2 \n(PD
-.nr PD 0
-.IP \ \ \(bu
-the \fB$0\fP parameter is set to the name of the function
-(Bourne-style functions leave \fB$0\fP untouched).
-.IP \ \ \(bu
-parameter assignments preceeding function calls are not kept in
-the shell environment
-(executing Bourne-style functions will keep assignments).
-.nr PD \n(P2
-In the future, the following differences will also be added:
-.nr P2 \n(PD
-.nr PD 0
-.IP \ \ \(bu
-A separate trap/signal environment will be used during the execution of
-functions.
-This will mean that traps set inside a function will not affect the shell's
-traps and signals that are not ignored in the shell (but may be trapped) will
-have their default effect in a function.
-.IP \ \ \(bu
-The EXIT trap, if set in a function, will be executed after the function
-returns.
-.nr PD \n(P2
-.\"}}}
-.\"{{{ POSIX mode
-.SS "POSIX Mode"
-The shell is intended to be POSIX compliant, however, in some cases, POSIX
-behaviour is contrary either to the original Korn shell behaviour or to
-user convenience.
-How the shell behaves in these cases is determined by the state of
-the posix option (\fBset \-o posix\fP) \(em if it is on, the POSIX behaviour
-is followed, otherwise it is not.
-The \fBposix\fP option is set automatically when the shell starts up
-if the environment contains the \fBPOSIXLY_CORRECT\fP parameter.
-(The shell can also be compiled so that it is in POSIX mode by default,
-however this is usually not desirable).
-.PP
-The following is a list of things that are affected by the state of
-the \fBposix\fP option:
-.nr P2 \n(PD
-.nr PD 0
-.IP \ \ \(bu
-reading of \fB$ENV\fP: if not in posix mode, the \fBENV\fP parameter
-is not expanded and included when the shell starts.
-.IP \ \ \(bu
-\fB\e"\fP inside double quoted \fB`\fP..\fB`\fP command substitutions:
-in posix mode, the \fB\e"\fP is interpreted when the command is interpreted;
-in non-posix mode, the backslash is stripped before the command substitution
-is interpreted. For example, \fBecho "`echo \e"hi\e"`"\fP produces `"hi"' in
-posix mode, `hi' in non-posix mode. To avoid problems, use the \fB$(...\fP)
-form of command substitution.
-.IP \ \ \(bu
-\fBkill \-l\fP output: in posix mode, signal names are listed one a single line;
-in non-posix mode, signal numbers, names and descriptions are printed in
-columns.
-In future, a new option (\fB\-v\fP perhaps) will be added to distinguish
-the two behaviours.
-.IP \ \ \(bu
-\fBfg\fP exit status: in posix mode, the exit status is 0 if no errors occur;
-in non-posix mode, the exit status is that of the last foregrounded job.
-.IP \ \ \(bu
-\fBgetopts\fP: in posix mode, options must start with a \fB\-\fP; in non-posix
-mode, options can start with either \fB\-\fP or \fB+\fP.
-.IP \ \ \(bu
-brace expansion (also known as alternation): in posix mode, brace expansion
-is disabled; in non-posix mode, brace expansion enabled.
-Note that \fBset \-o posix\fP (or setting the \fBPOSIXLY_CORRECT\fP parameter)
-automatically turns the \fBbraceexpand\fP option off, however it can be
-explicitly turned on later.
-.IP \ \ \(bu
-\fBset \-\fP: in posix mode, this does not clear the \fBverbose\fP or
-\fBxtrace\fP options; in non-posix mode, it does.
-.IP \ \ \(bu
-\fBset\fP exit status: in posix mode, the exit status of set is 0
-if there are no errors; in non-posix mode, the exit status is that of
-any command substitutions performed in generating the set command.
-For example, `\fBset \-\- `false`; echo $?\fP' prints 0 in posix mode,
-1 in non-posix mode. This construct is used in most shell scripts that
-use the old \fIgetopt\fP(1) command.
-.IP \ \ \(bu
-argument expansion of \fBalias\fP, \fBexport\fP, \fBreadonly\fP, and
-\fBtypeset\fP commands: in posix mode, normal argument expansion done;
-in non-posix mode, field splitting, file globing, brace expansion and
-(normal) tilde expansion are turned off, and assignment tilde expansion
-is turned on.
-.IP \ \ \(bu
-signal specification: in posix mode, signals can be specified as digits only
-if signal numbers match POSIX values (\fIi.e.\fP, HUP=1, INT=2, QUIT=3, ABRT=6,
-KILL=9, ALRM=14, and TERM=15); in non-posix mode, signals can be always digits.
-.IP \ \ \(bu
-alias expansion: in posix mode, alias expansion is only carried out when
-reading command words; in non-posix mode, alias expansion is carried out
-on any word following an alias that ended in a space.
-For example, the following for loop
-.RS
-.ft B
-alias a='for ' i='j'
-.br
-a i in 1 2; do echo i=$i j=$j; done
-.ft P
-.RE
-uses parameter \fBi\fP in posix mode, \fBj\fP in non-posix mode.
-.nr PD \n(P2
-.\"}}}
-.\"{{{ Command Execution (built-in commands)
-.SS "Command Execution"
-After evaluation of command line arguments, redirections and parameter
-assignments, the type of command is determined: a special built-in,
-a function, a regular built-in or the name of a file to execute found
-using the \fBPATH\fP parameter.
-The checks are made in the above order.
-Special built-in commands differ from other commands in that
-the \fBPATH\fP parameter is not used to find them, an error
-during their execution can cause a non-interactive shell to exit and
-parameter assignments that are specified before the command are
-kept after the command completes.
-Just to confuse things, if the posix option is turned off (see \fBset\fP
-command below) some special commands are very special in that
-no field splitting, file globing, brace expansion nor tilde expansion
-is preformed on arguments that look like assignments.
-Regular built-in commands are different only in that the \fBPATH\fP
-parameter is not used to find them.
-.PP
-The original ksh and POSIX differ somewhat in which commands are considered
-special or regular:
-.IP "POSIX special commands"
-.TS
-lw(8m)fB lw(8m)fB lw(8m)fB lw(8m)fB lw(8m)fB .
-\&. continue exit return trap
-: eval export set unset
-break exec readonly shift
-.TE
-.IP "Additional ksh special commands"
-.TS
-lw(8m)fB lw(8m)fB lw(8m)fB lw(8m)fB lw(8m)fB .
-builtin times typeset
-.TE
-.IP "Very special commands (non-posix mode)"
-.TS
-lw(8m)fB lw(8m)fB lw(8m)fB lw(8m)fB lw(8m)fB .
-alias readonly set typeset
-.TE
-.IP "POSIX regular commands"
-.TS
-lw(8m)fB lw(8m)fB lw(8m)fB lw(8m)fB lw(8m)fB .
-alias command fg kill umask
-bg false getopts read unalias
-cd fc jobs true wait
-.TE
-.IP "Additional ksh regular commands"
-.TS
-lw(8m)fB lw(8m)fB lw(8m)fB lw(8m)fB lw(8m)fB .
-[ let pwd ulimit
-echo print test whence
-.TE
-.PP
-In the future, the additional ksh special and regular commands may
-be treated differently from the POSIX special and regular commands.
-.PP
-Once the type of the command has been determined, any command line parameter
-assignments are performed and exported for the duration of the command.
-.PP
-The following describes the special and regular built-in commands:
-.\"{{{ . file [ arg1 ... ]
-.IP "\fB\&.\fP \fIfile\fP [\fIarg1\fP ...]"
-Execute the commands in \fIfile\fP in the current environment.
-The file is searched for in the directories of \fBPATH\fP.
-If arguments are given, the positional parameters may be used to
-access them while \fIfile\fP is being executed.
-If no arguments are given, the positional parameters are those of the
-environment the command is used in.
-.\"}}}
-.\"{{{ : [ ... ]
-.IP "\fB:\fP [ ... ]"
-The null command.
-Exit status is set to zero.
-.\"}}}
-.\"{{{ alias [ -d | -t [ -r ] ] [-x] [name1[=value1] ...]
-.IP "\fBalias\fP [ \fB\-d\fP | \fB\-t\fP [\fB\-r\fP] ] [\fB\-x\fP] [\fIname1\fP[\fB=\fP\fIvalue1\fP] ...]"
-Without arguments, \fBalias\fP lists all aliases and their values. For
-any name without a value, its value is listed. Any name with a value
-defines an alias (see Aliases above).
-.sp
-The \fB\-x\fP option sets the export attribute of an alias, or, if no
-names are given, lists the aliases with the export attribute
-(exporting an alias currently has no affect).
-.sp
-The \fB\-t\fP option indicates that tracked aliases are to be listed/set
-(values specified on the command line are ignored for tracked aliases).
-The \fB\-r\fP option indicates that all tracked aliases are to be reset.
-.sp
-The \fB\-d\fP causes directory aliases, which are used in tilde expansion,
-to be listed or set (see Tilde Expansion above).
-.\"}}}
-.\"{{{ bg [job ...]
-.IP "\fBbg\fP [\fIjob\fP ...]"
-Resume the specified stopped job(s) in the background.
-If no jobs are specified, \fB%+\fP is assumed.
-This command is only available on systems which support job control.
-See Job Control below for more information.
-.\"}}}
-.\"{{{ bind [-l] [-m] [key[=editing-command] ...]
-.IP "\fBbind\fP [\fB\-m\fP] [\fIkey\fP[\fB=\fP\fIediting-command\fP] ...]"
-Set or view the current emacs command editing key bindings/macros.
-See Emacs Interactive Input Line Editing below for a complete description.
-.\"}}}
-.\"{{{ break [level]
-.IP "\fBbreak\fP [\fIlevel\fP]"
-\fBbreak\fP exits the \fIlevel\fPth inner most for, select, until, or while
-loop.
-\fIlevel\fP defaults to 1.
-.\"}}}
-.\"{{{ builtin command [arg1 ...]
-.IP "\fBbuiltin\fP \fIcommand\fP [\fIarg1\fP ...]"
-Execute the built-in command \fIcommand\fP.
-.\"}}}
-.\"{{{ cd [-LP] [dir]
-.IP "\fBcd\fP [\fB\-LP\fP] [\fIdir\fP]"
-Set the working directory to \fIdir\fP. If the parameter \fBCDPATH\fP
-is set, it lists the search path for the directory containing
-\fIdir\fP. A null path means the current directory. If \fIdir\fP is
-missing, the home directory \fB$HOME\fP is used. If \fIdir\fP is
-\fB\-\fP, the previous working directory is used (see OLDPWD parameter).
-If \fB\-L\fP option (logical path) is used or if the \fBphysical\fP option
-(see \fBset\fP command below) isn't set, references to \fB..\fP in \fIdir\fP
-are relative to the path used get to the directory.
-If \fB\-P\fP option (physical path) is used or if the \fBphysical\fP option
-is set, \fB..\fP is relative to the filesystem directory tree.
-The \fBPWD\fP and \fBOLDPWD\fP parameters are updated to reflect the
-current and old wording directory, respectively.
-.\"}}}
-.\"{{{ cd [-LP] old new
-.IP "\fBcd\fP [\fB\-LP\fP] \fIold new\fP"
-The string \fInew\fP is substituted for \fIold\fP in the current
-directory, and the shell attempts to change to the new directory.
-.\"}}}
-.\"{{{ command [ -pvV ] cmd [arg1 ...]
-.IP "\fBcommand\fP [\fB\-p\fP] \fIcmd\fP [\fIarg1\fP ...]"
-\fIcmd\fP
-is executed exactly as if the \fBcommand\fP had not been specified,
-with two exceptions: first, \fIcmd\fP cannot be a shell function, and
-second, special built-in commands lose their specialness (\fIi.e.\fP,
-redirection and utility errors do not cause the shell to exit, and command
-assignments are not permanent).
-If the \fB\-p\fP option is given, a default search path is used instead of
-the current value of \fBPATH\fP (the actual value of the default path is
-system dependent: on POSIXish systems, it is the value returned by
-.ce
-\fBgetconf CS_PATH\fP
-).
-.sp
-.\"}}}
-.\"{{{ continue [levels]
-.IP "\fBcontinue\fP [\fIlevels\fP]"
-\fBcontinue\fP jumps to the beginning of the \fIlevel\fPth inner most for,
-select, until, or while loop.
-\fIlevel\fP defaults to 1.
-.\"}}}
-.\"{{{ echo [-neE] [arg ...]
-.IP "\fBecho\fP [\fB\-neE\fP] [\fIarg\fP ...]"
-Prints its arguments (separated by spaces) followed by a newline, to
-standard out.
-The newline is suppressed if any of the arguments contain the backslash
-sequence \fB\ec\fP.
-See \fBprint\fP command below for a list of other backslash sequences
-that are recognized.
-.sp
-The options are provided for compatibility with BSD shell scripts:
-\fB\-n\fP suppresses the trailing newline, \fB\-e\fP enables backslash
-interpretation (a no-op, since this is normally done), and \fB\-E\fP which
-suppresses backslash interpretation.
-.\"}}}
-.\"{{{ eval command ...
-.IP "\fBeval\fP \fIcommand ...\fP"
-The arguments are concatenated (with spaces between them) to form
-a single string which the shell then parses and executes
-in the current environment.
-.\"}}}
-.\"{{{ exec [command [arg ...]]
-.IP "\fBexec\fP [\fIcommand\fP [\fIarg\fP ...]]"
-The command is executed without forking, replacing the shell process.
-.sp
-If no arguments are given, any IO redirection is permanent and the shell
-is not replaced.
-.\"}}}
-.\"{{{ exit [status]
-.IP "\fBexit\fP [\fIstatus\fP]"
-The shell exits with the specified exit status.
-If \fIstatus\fP is not specified, the exit status is the current
-value of the \fB?\fP parameter.
-.\"}}}
-.\"{{{ export [-p] [parameter[=value] ...]
-.IP "\fBexport\fP [\fB\-p\fP] [\fIparameter\fP[\fB=\fP\fIvalue\fP]] ..."
-Sets the export attribute of the named parameters.
-Exported parameters are passed in the environment to executed commands.
-If values are specified, the named parameters also assigned.
-.sp
-If no parameters are specified, the names of all parameters with the export
-attribute are printed one per line, unless the \fB\-p\fP option is used,
-in which case \fBexport\fP commands defining all exported
-parameters, including their values, are printed.
-.\"}}}
-.\"{{{ false
-.IP "\fBfalse\fP"
-A command that exits with a non-zero status.
-.\"}}}
-.\"{{{ fc [-e editor | -l [-n]] [-r] [first [ last ]]
-.\"}}}
-.\"{{{ fc [-e - | -s] [-g] [old=new] [prefix]
-.IP "\fBfc\fP [\fB\-e \-\fP | \fB\-s\fP] [\fB\-g\fP] [\fIold\fP\fB=\fP\fInew\fP] [\fIprefix\fP]"
-Re-execute the selected command (the previous command by default) after
-performing the optional substitution of \fIold\fP with \fInew\fP. If
-\fB\-g\fP is specified, all occurrences of \fIold\fP are replaced with
-\fInew\fP. This command is usually accessed with the predefined alias
-\fBr='fc \-e \-'\fP.
-.\"}}}
-.\"{{{ fg [job ...]
-.IP "\fBfg\fP [\fIjob\fP ...]"
-Resume the specified job(s) in the foreground.
-If no jobs are specified, \fB%+\fP is assumed.
-This command is only available on systems which support job control.
-See Job Control below for more information.
-.\"}}}
-.\"{{{ getopts optstring name [arg ...]
-.IP "\fBgetopts\fP \fIoptstring\fP \fIname\fP [\fIarg\fP ...]"
-\fBgetopts\fP is used by shell procedures to parse the specified arguments
-(or positional parameters, if no arguments are given) and to check for legal
-options.
-\fIoptstring\fP contains the option letters that
-\fBgetopts\fP is to recognize. If a letter is followed by a colon, the
-option is expected to have an argument.
-Arguments containing options must all start with either a \fB\-\fP or
-a \fB+\fP, options that do not take arguments may be grouped in a single
-argument.
-If an option takes an argument and the option character is not the last
-character of the argument it is found in, the remainder of the argument
-is taken to be the option's argument, otherwise, the next argument is
-the option's argument.
-.sp
-Each time \fBgetopts\fP is invoked, it places the next option in
-the shell parameter \fIname\fP and the index of the next argument to be
-processed in the shell parameter \fBOPTIND\fP.
-If the option was introduced with a \fB+\fP, the option placed in
-\fIname\fP is prefixed with a \fB+\fP.
-When an option requires an argument, \fBgetopts\fP places it in the
-shell parameter \fBOPTARG\fP.
-When an illegal option or a missing option argument is
-encountered a question mark or a colon is placed in \fIname\fP
-(indicating an illegal option or missing argument, respectively)
-and \fBOPTARG\fP is set to the option character that caused the problem.
-An error message is also printed to standard error if \fIoptstring\fP
-does not begin with a colon.
-.sp
-When the end of the options is encountered, \fBgetopts\fP exits with a
-non-zero exit status.
-Options end at the first (non-option argument) argument that does not
-start with a \-, or when a \fB\-\-\fP argument is encountered.
-.sp
-Option parsing can be reset by setting \fBOPTIND\fP to 1 (this is done
-automatically whenever the shell or a shell procedure is invoked).
-.sp
-Warning: Changing the value of the shell parameter \fBOPTIND\fP to
-a value other than 1, or parsing different sets of arguments without
-resetting \fBOPTIND\fP may lead to unexpected results.
-.\"}}}
-.\"{{{ hash [-r] [name ...]
-.IP "\fBhash\fP [\fB\-r\fP] [\fIname ...\fP]"
-Without arguments, any hashed executable command pathnames are listed.
-The \fB\-r\fP option causes all hashed commands to be removed
-from the hash table.
-Each \fIname\fP is searched as if it where a command name and added to the
-hash table if it is an executable command.
-.\"}}}
-.\"{{{ jobs [-lpn] [job ...]
-.IP "\fBjobs\fP [\fB\-lpn\fP] [\fIjob\fP ...]"
-Display information about the specified jobs; if no jobs are specified,
-all jobs are displayed.
-The \fB\-n\fP option causes information to be displayed only for jobs
-that have changed state since the last notification.
-If the \fB\-l\fP option is used, the process-id of each process in a job
-is also listed.
-The \fB\-p\fP option causes only the process group of each job to be printed.
-See Job Control below for the format of \fIjob\fP and the displayed job.
-.\"}}}
-.\"{{{ kill [-s signame | -signum | -signame] { job | pid | -pgrp } ...
-.IP "\fBkill\fP [\fB\-s\fP \fIsigname\fP | \fB\-signum\fP | \fB\-signame\fP ] { \fIjob\fP | \fIpid\fP | \fB\-\fP\fIpgrp\fP } ..."
-Send the specified signal to the specified jobs, process ids, or process groups.
-If no signal is specified, the signal TERM is sent.
-If a job is specified, the signal is sent to the job's process group.
-See Job Control below for the format of \fIjob\fP.
-.\"}}}
-.\"{{{ kill -l [exit-status ...]
-.IP "\fBkill \-l\fP [\fIexit-status\fP ...]"
-Print the name of the signal that killed a process which exited with
-the specified \fIexit-status\fPes.
-If no arguments are specified, a list of all the signals, their numbers and
-a short description of them are printed.
-.\"}}}
-.\"{{{ let [expression ...]
-.\"}}}
-.\"{{{ print [-nprsun | -R [-en]] [argument ...]
-.IP "\fBprint\fP [\fB\-nprsu\fP\fIn\fP | \fB\-R\fP [\fB\-en\fP]] [\fIargument ...\fP]"
-\fBPrint\fP prints its arguments on the standard output, separated by
-spaces, and terminated with a newline. The \fB\-n\fP option suppresses
-the newline. By default, certain C escapes are translated. These
-include \eb, \ef, \en, \er, \et, \ev, and \e0### (# is an octal digit, of
-which there may be 0 to 3).
-\ec is equivalent to using the \fB\-n\fP option. \e expansion may be
-inhibited with the \fB\-r\fP option.
-The \fB\-s\fP option prints to the history file instead of standard output,
-the \fB\-u\fP option prints to file descriptor \fIn\fP (\fIn\fP
-defaults to 1 if omitted), and the \fB\-p\fP option prints to the co-process
-(see Co-Processes above).
-.sp
-The \fB\-R\fP option is used to emulate, to some degree, the BSD echo
-command, which does not process \e sequences unless the \fB\-e\fP option
-is given.
-As above, the \fB\-n\fP option suppresses the trailing newline.
-.\"}}}
-.\"{{{ pwd [-LP]
-.IP "\fBpwd\fP [\fB\-LP\fP]"
-Print the present working directory.
-If \fB\-L\fP option is used or if the \fBphysical\fP option
-(see \fBset\fP command below) isn't set, the logical path is printed
-(\fIi.e.\fP, the path used to \fBcd\fP to the current directory).
-If \fB\-P\fP option (physical path) is used or if the \fBphysical\fP option
-is set, the path determined from the filesystem (by following \fB..\fP
-directories to the root directory) is printed.
-.\"}}}
-.\"{{{ read [-prsun] [parameter ...]
-.IP "\fBread\fP [\fB\-prsu\fP\fIn\fP] [\fIparameter ...\fP]"
-Reads a line of input from standard input, separate the line into fields using
-the \fBIFS\fP parameter (see Substitution above), and assign each field to the
-specified parameters.
-If there are more parameters than fields, the extra parameters are set to null,
-or alternatively, if there are more fields than parameters, the last parameter
-is assigned the remaining fields (inclusive of any separating spaces).
-If no parameters are specified, the \fBREPLY\fP parameter is used.
-If the input line ends in a backslash and the \fB\-r\fP option was not used, the
-backslash and newline are stripped and more input is read.
-If no input is read, \fBread\fP exits with a non-zero status.
-.sp
-The first parameter may have a question mark and a string appended to it, in
-which case the string is used as a prompt (printed to standard error before
-any input is read) if the input is a tty
-(\fIe.g.\fP, \fBread nfoo?'number of foos: '\fP).
-.sp
-The \fB\-u\fP\fIn\fP and \fB\-p\fP options cause input to be read
-from file descriptor \fIn\fP or the current co-process (see Co-Processes above
-for comments on this), respectively.
-If the \fB\-s\fP option is used, input is saved to the history file.
-.\"}}}
-.\"{{{ readonly [-p] [parameter[=value] ...]
-.IP "\fBreadonly\fP [\fB\-p\fP] [\fIparameter\fP[\fB=\fP\fIvalue\fP]] ..."
-Sets the readonly attribute of the named parameters. If values are given,
-parameters are set to them before setting the attribute.
-Once a parameter is made readonly, it cannot be unset and its value cannot
-be changed.
-.sp
-If no parameters are specified, the names of all parameters with the readonly
-attribute are printed one per line, unless the \fB\-p\fP option is used,
-in which case \fBreadonly\fP commands defining all readonly
-parameters, including their values, are printed.
-.\"}}}
-.\"{{{ return [status]
-.IP "\fBreturn\fP [\fIstatus\fP]"
-Returns from a function or \fB.\fP script, with exit status \fIstatus\fP.
-If no \fIstatus\fP is given, the exit status of the last executed command
-is used.
-If used outside of a function or \fB.\fP script, it has the same effect
-as \fBexit\fP.
-Note that pdksh treats both profile and \fB$ENV\fP files as \fB.\fP scripts,
-while the original Korn shell only treats profiles as \fB.\fP scripts.
-.\"}}}
-.\"{{{ set [+-abCefhkmnpsuvxX] [+-o [option]] [+-A name] [--] [arg ...]
-.IP "\fBset\fP [\fB\(+-abCefhkmnpsuvxX\fP] [\fB\(+-o\fP [\fIoption\fP]] [\fB\(+-A\fP \fIname\fP] [\fB\-\-\fP] [\fIarg\fP ...]"
-The set command can be used to set (\fB\-\fP) or clear (\fB+\fP) shell options,
-set the positional parameters, or set an array parameter.
-Options can be changed using the \fB\(+-o\fP \fIoption\fP syntax,
-where \fIoption\fP is the long name of an option, or using
-the \fB\(+-\fP\fIletter\fP syntax, where \fIletter\fP is the
-option's single letter name (not all options have a single letter name).
-The following table lists both option letters (if they exist) and long names
-along with a description of what the option does.
-.sp
-.TS
-expand;
-afB lfB lw(3i).
-\-A T{
-Sets the elements of the array parameter \fIname\fP to \fIarg\fP ...;
-If \fB\-A\fP is used, the array is reset (\fIi.e.\fP, emptied) first;
-if \fB+A\fP is used, the first N elements are set (where N is the number
-of \fIarg\fPs), the rest are left untouched.
-T}
-\-a allexport T{
-all new parameters are created with the export attribute
-T}
-\-b notify T{
-Print job notification messages asynchronously, instead of just before the
-prompt.
-Only used if job control is enabled (\fB\-m\fP).
-T}
-\-C noclobber T{
-Prevent \fB>\fP redirection from overwriting existing files (\fB>|\fP must
-be used to force an overwrite).
-T}
-\-e errexit T{
-Exit (after executing the \fBERR\fP trap) as soon as an error occurs or
-a command fails (\fIi.e.\fP, exits with a non-zero status).
-This does not apply to commands whose exit status is explicitly tested by a
-shell construct such as \fBif\fP, \fBuntil\fP, \fBwhile\fP, \fB&&\fP or
-\fB||\fP statements.
-T}
-\-f noglob T{
-Do not expand file name patterns.
-T}
-\-h trackall T{
-Create tracked aliases for all executed commands (see Aliases above).
-On by default for non-interactive shells.
-T}
-\-i interactive T{
-Enable interactive mode \- this can only be set/unset when the shell is
-invoked.
-T}
-\-k keyword T{
-Parameter assignments are recognized anywhere in a command.
-T}
-\-l login T{
-The shell is a login shell \- this can only be set/unset when the shell is
-invoked (see Shell Startup above).
-T}
-\-m monitor T{
-Enable job control (default for interactive shells).
-T}
-\-n noexec T{
-Do not execute any commands \- useful for checking the syntax of scripts
-(ignored if interactive).
-T}
-\-p privileged T{
-Set automatically if, when the shell starts, the read uid or gid does not
-match the effective uid or gid, respectively.
-See Shell Startup above for a description of what this
-means.
-T}
--r restricted T{
-Enable restricted mode \(em this option can only be used when the shell is
-invoked. See Shell Startup above for a description of what this
-means.
-T}
-\-s stdin T{
-If used when the shell is invoked, commands are read from standard input.
-Set automatically if the shell is invoked with no arguments.
-.sp
-When \fB\-s\fP is used in the \fBset\fP command, it causes the specified
-arguments to be sorted before assigning them to the positional parameters
-(or to array \fIname\fP, if \fB\-A\fP is used).
-T}
-\-u nounset T{
-Referencing of an unset parameter is treated as an error, unless
-one of the \fB\-\fP, \fB+\fP or \fB=\fP modifiers is used.
-T}
-\-v verbose T{
-Write shell input to standard error as it is read.
-T}
-\-x xtrace T{
-Print commands and parameter assignments when they are executed,
-preceded by the value of \fBPS4\fP.
-T}
-\-X markdirs T{
-Mark directories with a trailing \fB/\fP during file name generation.
-T}
- bgnice T{
-Background jobs are run with lower priority.
-T}
- ignoreeof T{
-The shell will not exit on when end-of-file is read, \fBexit\fP must be used.
-T}
- nohup T{
-Do not kill running jobs with a \fBHUP\fP signal when a login shell exists.
-Currently set by default, but this will change in the future to be compatible
-with the original Korn shell (which doesn't have this option, but does
-send the \fBHUP\fP signal).
-T}
- nolog T{
-No effect \- in the original Korn shell, this prevents function definitions
-from being stored in the history file.
-T}
- physical T{
-Causes the \fBcd\fP and \fBpwd\fP commands to use `physical'
-(\fIi.e.\fP, the filesystem's) \fB..\fP directories instead of `logical'
-directories (\fIi.e.\fP, the shell handles \fB..\fP, which allows the user
-to be obliveous of symlink links to directories).
-Clear by default. Note that setting
-this option does not effect the current value of the \fBPWD\fP parameter;
-only the \fBcd\fP command changes \fBPWD\fP.
-See the \fBcd\fP and \fBpwd\fP commands above for more details.
-T}
- posix T{
-Enable posix mode. See POSIX Mode above.
-T}
- vi T{
-Enable vi-like command line editing (interactive shells only).
-T}
- viraw T{
-No effect \- in the original Korn shell, unless viraw was set, the vi command
-line mode would let the tty driver do the work until ESC (^[) was entered.
-pdksh is always in viraw mode.
-T}
- vi-esccomplete T{
-In vi command line editing, do command / file name completion when
-escape (^[) is entered in command mode.
-T}
- vi-show8 T{
-Prefix characters with the eighth bit set with `M-'.
-If this option is not set, characters in the range
-128-160 are printed as is, which may cause problems.
-T}
- vi-tabcomplete T{
-In vi command line editing, do command / file name completion when
-tab (^I) is entered in insert mode.
-T}
-.TE
-.sp
-These options can also be used upon invocation of the shell. The current
-set of options (with single letter names) can be found in the
-parameter \fB\-\fP.
-\fBset -o\fP with no option name will list all the options and whether each
-is on or off; \fBset +o\fP will print the long names of all options that
-are currently on.
-.sp
-Remaining arguments, if any, are positional parameters and are assigned,
-in order, to the
-positional parameters (\fIi.e.\fP, \fB1\fP, \fB2\fP, \fIetc.\fP).
-If options are ended with \fB\-\-\fP and there are no remaining arguments,
-all positional parameters are cleared.
-If no options or arguments are given, then the values of all names are printed.
-For unknown historical reasons, a lone \fB\-\fP option is treated specially:
-it clears both the \fB\-x\fP and \fB\-v\fP options.
-.\"}}}
-.\"{{{ shift [number]
-.IP "\fBshift\fP [\fInumber\fP]"
-The positional parameters \fInumber\fP+1, \fInumber\fP+2 \fIetc.\fP\& are
-renamed to \fB1\fP, \fB2\fP, \fIetc.\fP
-\fInumber\fP defaults to 1.
-.\"}}}
-.\"{{{ test expression, [ expression ]
-.IP "\fBtest\fP \fIexpression\fP"
-.IP "\fB[\fP \fIexpression\fP \fB]\fP"
-\fBtest\fP evaluates the \fIexpression\fP and returns zero status if
-true, and 1 status if false and greater than 1 if there was an error.
-It is normally used as the
-condition command of \fBif\fP and \fBwhile\fP statements.
-The following basic expressions are available:
-.sp
-.TS
-afB ltw(2.8i).
-\fIstr\fP T{
-\fIstr\fP has non-zero length. Note that there is the potential
-for problems if \fIstr\fP turns out to be an operator (\fIe.g.\fP, \fB-r\fP)
-- it is generally better to use a test like
-.RS
-\fB[ X"\fP\fIstr\fP\fB" != X ]\fP
-.RE
-instead (double quotes are used in case \fIstr\fP contains spaces or file
-globing characters).
-T}
-\-r \fIfile\fP T{
-\fIfile\fP exists and is readable
-T}
-\-w \fIfile\fP T{
-\fIfile\fP exists and is writable
-T}
-\-x \fIfile\fP T{
-\fIfile\fP exists and is executable
-T}
-\-a \fIfile\fP T{
-\fIfile\fP exists
-T}
-\-e \fIfile\fP T{
-\fIfile\fP exists
-T}
-\-f \fIfile\fP T{
-\fIfile\fP is a regular file
-T}
-\-d \fIfile\fP T{
-\fIfile\fP is a directory
-T}
-\-c \fIfile\fP T{
-\fIfile\fP is a character special device
-T}
-\-b \fIfile\fP T{
-\fIfile\fP is a block special device
-T}
-\-p \fIfile\fP T{
-\fIfile\fP is a named pipe
-T}
-\-u \fIfile\fP T{
-\fIfile\fP's mode has setuid bit set
-T}
-\-g \fIfile\fP T{
-\fIfile\fP's mode has setgid bit set
-T}
-\-k \fIfile\fP T{
-\fIfile\fP's mode has sticky bit set
-T}
-\-s \fIfile\fP T{
-\fIfile\fP is not empty
-T}
-\-O \fIfile\fP T{
-\fIfile\fP's owner is the shell's effective user-ID
-T}
-\-G \fIfile\fP T{
-\fIfile\fP's group is the shell's effective group-ID
-T}
-\-h \fIfile\fP T{
-\fIfile\fP is a symbolic link
-T}
-\-H \fIfile\fP T{
-\fIfile\fP is a context dependent directory (only useful on HP-UX)
-T}
-\-L \fIfile\fP T{
-\fIfile\fP is a symbolic link
-T}
-\-S \fIfile\fP T{
-\fIfile\fP is a socket
-T}
-\-o \fIoption\fP T{
-shell \fIoption\fP is set (see \fBset\fP command above for list of options).
-As a non-standard extension, if the option starts with a \fB!\fP, the test
-is negated; the test always fails if option doesn't exist (thus
-.RS
-\fB[ -o \fP\fIfoo\fP \fB-o -o !\fP\fIfoo\fP \fB]\fP
-.RE
-returns true if and only if option \fIfoo\fP exists).
-T}
-\fIfile\fP \-nt \fIfile\fP T{
-first \fIfile\fP is newer than second \fIfile\fP
-T}
-\fIfile\fP \-ot \fIfile\fP T{
-first \fIfile\fP is older than second \fIfile\fP
-T}
-\fIfile\fP \-ef \fIfile\fP T{
-first \fIfile\fP is the same file as second \fIfile\fP
-T}
-\-t [\fIfd\fP] T{
-file descriptor is a tty device.
-Default value of \fIfd\fP is 1.
-T}
-\fIstring\fP T{
-\fIstring\fP is not empty
-T}
-\-z \fIstring\fP T{
-\fIstring\fP is empty
-T}
-\-n \fIstring\fP T{
-\fIstring\fP is not empty
-T}
-\fIstring\fP = \fIstring\fP T{
-strings are equal
-T}
-\fIstring\fP != \fIstring\fP T{
-strings are not equal
-T}
-\fInumber\fP \-eq \fInumber\fP T{
-numbers compare equal
-T}
-\fInumber\fP \-ne \fInumber\fP T{
-numbers compare not equal
-T}
-\fInumber\fP \-ge \fInumber\fP T{
-numbers compare greater than or equal
-T}
-\fInumber\fP \-gt \fInumber\fP T{
-numbers compare greater than
-T}
-\fInumber\fP \-le \fInumber\fP T{
-numbers compare less than or equal
-T}
-\fInumber\fP \-lt \fInumber\fP T{
-numbers compare less than
-T}
-.TE
-.sp
-The above basic expressions, in which unary operators have precedence over
-binary operators, may be combined with the following operators
-(listed in increasing order of precedence):
-.sp
-.TS
-afB l.
-\fIexpr\fP \-o \fIexpr\fP logical or
-\fIexpr\fP \-a \fIexpr\fP logical and
-! \fIexpr\fP logical not
-( \fIexpr\fP ) grouping
-.TE
-.sp
-On operating systems not supporting \fB/dev/fd/\fP\fIn\fP devices
-(where \fIn\fP is a file descriptor number),
-the \fBtest\fP command will attempt to fake it for all tests that
-operate on files (except the \fB-e\fP test).
-I.e., \fB[ -w /dev/fd/2 ]\fP tests if file descriptor 2 is writable.
-.sp
-Note that some special rules are applied (courtesy of POSIX) if the
-number of arguments to \fBtest\fP or \fB[\fP \&... \fB]\fP is less than
-five: if leading \fB!\fP arguments can be stripped such that only one
-argument remains then a string length test is performed (again, even if
-the argument is a unary operator);
-if leading \fB!\fP arguments can be stripped such that three
-arguments remain and the second argument is a binary operator, then the
-binary operation is performed (even if first argument is a unary
-operator, including an unstripped \fB!\fP).
-.sp
-\fBNote:\fP A common mistake is to use \fBif [ $foo = bar ]\fP which
-fails if parameter \fBfoo\fP is null or unset, if it has embedded spaces
-(\fIi.e.\fP, \fBIFS\fP characters), or if it is a unary operator like \fB!\fP or
-\fB\-n\fP. Use tests like \fBif [ "X$foo" = Xbar ]\fP instead.
-.\"}}}
-.\"{{{ times
-.IP \fBtimes\fP
-Print the accumulated user and system times used by the shell and by
-processes which have exited that the shell started.
-.\"}}}
-.\"{{{ trap [handler signal ...]
-.IP "\fBtrap\fP [\fIhandler\fP \fIsignal ...\fP]"
-Sets trap handler that is to be executed when any of the specified signals
-are received.
-\fBHandler\fP is either a null string, indicating the signals are to
-be ignored, a minus (\fB\-\fP), indicating that the default action is to
-be taken for the signals (see signal(2 or 3)), or a string containing shell
-commands to be evaluated and executed at the first opportunity (\fIi.e.\fP,
-when the current command completes, or before printing the next \fBPS1\fP
-prompt) after receipt of one of the signals.
-\fBSignal\fP is the name of a signal (\fIe.g.\fP, PIPE or ALRM) or the number
-of the signal (see \fBkill \-l\fP command above).
-There are two special signals: \fBEXIT\fP (also known as \fB0\fP), which
-is executed when the shell is about to exit, and \fBERR\fP which is
-executed after an error occurs (an error is something that would cause
-the shell to exit if the \fB\-e\fP or \fBerrexit\fP option were set \(em
-see \fBset\fP command above).
-\fBEXIT\fP handlers are executed in the environment of the last executed
-command.
-Note that for non-interactive shells, the trap handler cannot be changed for
-signals that were ignored when the shell started.
-.sp
-With no arguments, \fBtrap\fP lists, as a series of \fBtrap\fP commands,
-the current state of the traps that have been set since the shell started.
-.sp
-.\" todo: add these features (trap DEBUG, trap ERR/EXIT in function)
-The original Korn shell's \fBDEBUG\fP trap and the handling of \fBERR\fP and
-\fBEXIT\fP traps in functions are not yet implemented.
-.\"}}}
-.\"{{{ true
-.IP \fBtrue\fP
-A command that exits with a zero value.
-.\"}}}
-.\"{{{ typeset [[+-Ulrtux] [-L[n]] [-R[n]] [-Z[n]] [-i[n]] | -f [-tux]] [name[=value] ...]
-.IP "\fBtypeset\fP [[\(+-Ulrtux] [\fB\-L\fP[\fIn\fP]] [\fB\-R\fP[\fIn\fP]] [\fB\-Z\fP[\fIn\fP]] [\fB\-i\fP[\fIn\fP]] | \fB\-f\fP [\fB\-tux\fP]] [\fIname\fP[\fB=\fP\fIvalue\fP] ...]"
-Display or set parameter attributes.
-With no \fIname\fP arguments, parameter attributes are displayed: if no options
-arg used, the current attributes of all parameters are printed as typeset
-commands; if an option is given (or \fB\-\fP with no option letter)
-all parameters and their values with the specified attributes are printed;
-if options are introduced with \fB+\fP, parameter values are not printed.
-.sp
-If \fIname\fP arguments are given, the attributes of the named parameters
-are set (\fB\-\fP) or cleared (\fB+\fP).
-Values for parameters may optionally be specified.
-If typeset is used inside a function, any newly created parameters are local
-to the function.
-.sp
-When \fB\-f\fP is used, typeset operates on the attributes of functions.
-As with parameters, if no \fIname\fPs are given, functions are listed
-with their values (\fIi.e.\fP, definitions) unless options are introduced with
-\fB+\fP, in which case only the function names are reported.
-.sp
-.TS
-expand;
-afB lw(4.5i).
-\-L\fIn\fP T{
-Left justify attribute: \fIn\fP specifies the field width.
-If \fIn\fP is not specified, the current width of a parameter (or the
-width of its first assigned value) is used.
-Leading white space (and zeros, if used with the \fB\-Z\fP option) is stripped.
-If necessary, values are either truncated or space padded to fit the
-field width.
-T}
-\-R\fIn\fP T{
-Right justify attribute: \fIn\fP specifies the field width.
-If \fIn\fP is not specified, the current width of a parameter (or the
-width of its first assigned value) is used.
-Trailing white space are stripped.
-If necessary, values are either stripped of leading characters
-or space padded to make them fit the field width.
-T}
-\-Z\fIn\fP T{
-Zero fill attribute: if not combined with \fB\-L\fP, this is the
-same as \fB\-R\fP, except zero padding is used instead of space padding.
-T}
-\-i\fIn\fP T{
-integer attribute:
-\fIn\fP specifies the base to use when displaying the integer
-(if not specified, the base given in the first assignment is used).
-Parameters with this attribute may be assigned values containing
-arithmetic expressions.
-T}
-\-U T{
-unsigned integer attribute: integers are printed as unsigned values
-(only useful when combined with the \fB\-i\fP option).
-This option is not in the original Korn shell.
-T}
-\-f T{
-Function mode: display or set functions and their attributes, instead of
-parameters.
-T}
-\-l T{
-Lower case attribute: all upper case characters in values are converted to
-lower case.
-(In the original Korn shell, this parameter meant `long integer' when used
-with the \fB\-i\fP option).
-T}
-\-r T{
-Readonly attribute: parameters with the this attribute may not be assigned to
-or unset.
-Once this attribute is set, it can not be turned off.
-T}
-\-t T{
-Tag attribute: has no meaning to the shell; provided for application use.
-.sp
-For functions, \fB\-t\fP is the trace attribute.
-When functions with the trace attribute are executed, the \fBxtrace\fP (\fB\-x\fP) shell option is temporarily turned on.
-T}
-\-u T{
-Upper case attribute: all lower case characters in values are converted to
-upper case.
-(In the original Korn shell, this parameter meant `unsigned integer' when used
-with the \fB\-i\fP option, which meant upper case letters would never be used
-for bases greater than 10. See the \fB\-U\fP option).
-.sp
-For functions, \fB\-u\fP is the undefined attribute. See Functions above
-for the implications of this.
-T}
-\-x T{
-Export attribute: parameters (or functions) are placed in the environment of
-any executed commands. Exported functions are not implemented yet.
-T}
-.TE
-.\"}}}
-.\"{{{ ulimit [-acdfHlmnpsStvw] [value]
-.IP "\fBulimit\fP [\fB\-acdfHlmnpsStvw\fP] [\fIvalue\fP]"
-Display or set process limits.
-If no options are used, the file size limit (\fB\-f\fP) is assumed.
-\fBvalue\fP, if specified, may be either be an arithmetic expression or the
-word \fBunlimited\fP.
-The limits affect the shell and any processes created by the shell after
-a limit is imposed.
-Note that some systems may not allow limits to be increased once they
-are set.
-Also note that the types of limits available are system dependent \- some
-systems have only the \fB\-f\fP limit.
-.RS
-.IP \fB\-a\fP
-Displays all limits; unless \fB\-H\fP is used, soft limits are displayed.
-.IP \fB\-H\fP
-Set the hard limit only (default is to set both hard and soft limits).
-.IP \fB\-S\fP
-Set the soft limit only (default is to set both hard and soft limits).
-.IP \fB\-c\fP
-Impose a size limit of \fIn\fP blocks on the size of core dumps.
-.IP \fB\-d\fP
-Impose a size limit of \fIn\fP kbytes on the size of the data area.
-.IP \fB\-f\fP
-Impose a size limit of \fIn\fP blocks on files written by the shell and
-its child processes (files of any size may be read).
-.IP \fB\-l\fP
-Impose a limit of \fIn\fP kbytes on the amount of locked (wired) physical
-memory.
-.IP \fB\-m\fP
-Impose a limit of \fIn\fP kbytes on the amount of physical memory used.
-.IP \fB\-n\fP
-Impose a limit of \fIn\fP file descriptors that can be open at once.
-.IP \fB\-p\fP
-Impose a limit of \fIn\fP processes that can be run by the user at any one
-time.
-.IP \fB\-s\fP
-Impose a size limit of \fIn\fP kbytes on the size of the stack area.
-.IP \fB\-t\fP
-Impose a time limit of \fIn\fP cpu seconds to be used by each process.
-.IP \fB\-v\fP
-Impose a limit of \fIn\fP kbytes on the amount of virtual memory used;
-on some systems this is the maximum allowable virtual address (in bytes,
-not kbytes).
-.IP \fB\-w\fP
-Impose a limit of \fIn\fP kbytes on the amount of swap space used.
-.PP
-As far as \fBulimit\fP is concerned, a block is 512 bytes.
-.RE
-.\"}}}
-.\"{{{ umask [-S] [mask]
-.IP "\fBumask\fP [\fB\-S\fP] [\fImask\fP]"
-.RS
-Display or set the file permission creation mask, or umask (see \fIumask\fP(2)).
-If the \fB\-S\fP option is used, the mask displayed or set is symbolic,
-otherwise it is an octal number.
-.sp
-Symbolic masks are like those used by \fIchmod\fP(1):
-.RS
-[\fBugoa\fP]{{\fB=+-\fP}{\fBrwx\fP}*}+[\fB,\fP...]
-.RE
-in which the first group of characters is the \fIwho\fP part, the second
-group is the \fIop\fP part, and the last group is the \fIperm\fP part.
-The \fIwho\fP part specifies which part of the umask is to be modified.
-The letters mean:
-.RS
-.IP \fBu\fP
-the user permissions
-.IP \fBg\fP
-the group permissions
-.IP \fBo\fP
-the other permissions (non-user, non-group)
-.IP \fBa\fP
-all permissions (user, group and other)
-.RE
-.sp
-The \fIop\fP part indicates how the \fIwho\fP permissions are to be modified:
-.RS
-.IP \fB=\fP
-set
-.IP \fB+\fP
-added to
-.IP \fB\-\fP
-removed from
-.RE
-.sp
-The \fIperm\fP part specifies which permissions are to be set, added or removed:
-.RS
-.IP \fBr\fP
-read permission
-.IP \fBw\fP
-write permission
-.IP \fBx\fP
-execute permission
-.RE
-.sp
-When symbolic masks are used, they describe what permissions may
-be made available (as opposed to octal masks in which a set bit means
-the corresponding bit is to be cleared).
-Example: `ug=rwx,o=' sets the mask so files will not be readable, writable
-or executable by `others', and is equivalent (on most systems) to the octal
-mask `07'.
-.RE
-.\"}}}
-.\"{{{ unalias [-adt] name ...
-.IP "\fBunalias\fP [\fB\-adt\fP] [\fIname1\fP ...]"
-The aliases for the given names are removed.
-If the \fB\-a\fP option is used, all aliases are removed.
-If the \fB\-t\fP or \fB\-d\fP options are used, the indicated operations
-are carried out on tracked or directory aliases, respectively.
-.\"}}}
-.\"{{{ unset [-fv] parameter ...
-.IP "\fBunset\fP [\fB\-fv\fP] \fIparameter\fP ..."
-Unset the named parameters (\fB\-v\fP, the default) or functions (\fB\-f\fP).
-The exit status is non-zero if any of the parameters were already unset,
-zero otherwise.
-.\"}}}
-.\"{{{ wait [job]
-.IP "\fBwait\fP [\fIjob\fP]"
-Wait for the specified job(s) to finish.
-The exit status of wait is that of the last specified job:
-if the last job is killed by a signal, the exit status is 128 + the
-number of the signal (see \fBkill \-l\fP \fIexit-status\fP above); if the last
-specified job can't be found (because it never existed, or had already
-finished), the exit status of wait is 127.
-See Job Control below for the format of \fIjob\fP.
-\fBWait\fP will return if a signal for which a trap has been set is received,
-or if a HUP, INT or QUIT signal is received.
-.sp
-If no jobs are specified, \fBwait\fP waits for all currently running jobs
-(if any) to finish and exits with a zero status.
-If job monitoring is enabled, the completion status of jobs is
-printed (this is not the case when jobs are explicitly specified).
-.\"}}}
-.\"{{{ whence [-pv] [name ...]
-.IP "\fBwhence\fP [\fB\-pv\fP] [name ...]"
-For each name, the type of command is listed (reserved word, built-in, alias,
-function, tracked alias or executable).
-If the \fB\-p\fP option is used, a path search done even if \fIname\fP
-is a reserved word, alias, \fIetc.\fP
-Without the \fB\-v\fP option, \fBwhence\fP is similar to \fBcommand \-v\fP
-except that \fBwhence\fP will find reserved words and won't print aliases
-as alias commands;
-with the \fB\-v\fP option, \fBwhence\fP is the same as \fBcommand \-V\fP.
-Note that for \fBwhence\fP, the \fB\-p\fP option does not affect the search
-path used, as it does for \fBcommand\fP.
-If the type of one or more of the names could not be determined, the
-exit status is non-zero.
-.\"}}}
-.\"}}}
-.\"{{{ job control (and its built-in commands)
-.SS "Job Control"
-Job control refers to the shell's ability to monitor and control \fBjobs\fP,
-which are processes or groups of processes created for commands or pipelines.
-At a minimum, the shell keeps track of the status of the background
-(\fIi.e.\fP, asynchronous) jobs that currently exist; this information can be
-displayed using the \fBjobs\fP command.
-If job control is fully enabled (using \fBset \-m\fP or
-\fBset \-o monitor\fP), as it is for interactive shells,
-the processes of a job are placed in their own process group,
-foreground jobs can be stopped by typing the suspend character from the
-terminal (normally ^Z),
-jobs can be restarted in either the foreground
-or background, using the \fBfg\fP and \fBbg\fP commands, respectively,
-and the state of the terminal is saved or restored when a foreground
-job is stopped or restarted, respectively.
-.sp
-Note that only commands that create processes (\fIe.g.\fP,
-asynchronous commands, subshell commands, and non-built-in,
-non-function commands) can be stopped; commands like \fBread\fP cannot be.
-.sp
-When a job is created, it is assigned a job-number.
-For interactive shells, this number is printed inside \fB[\fP..\fB]\fP,
-followed by the process-ids of the processes in the job when an asynchronous
-command is run.
-A job may be referred to in \fBbg\fP, \fBfg\fP, \fBjobs\fP, \fBkill\fP and
-\fBwait\fP commands either by the process id of the last process in the
-command pipeline (as stored in the \fB$!\fP parameter) or by prefixing the
-job-number with a percent sign (\fB%\fP).
-Other percent sequences can also be used to refer to jobs:
-.sp
-.TS
-expand;
-afB lw(4.5i).
-%+ T{
-The most recently stopped job, or, if there are no stopped jobs, the oldest
-running job.
-T}
-%%\fR, \fP% T{
-Same as \fB%+\fP.
-T}
-%\- T{
-The job that would be the \fB%+\fP job, if the later did not exist.
-T}
-%\fIn\fP T{
-The job with job-number \fIn\fP.
-T}
-%?\fIstring\fP T{
-The job containing the string \fIstring\fP (an error occurs if multiple jobs
-are matched).
-T}
-%\fIstring\fP T{
-The job starting with string \fIstring\fP (an error occurs if multiple jobs
-are matched).
-T}
-.TE
-.sp
-When a job changes state (\fIe.g.\fP, a background job finishes or foreground
-job is stopped), the shell prints the following status information:
-.RS
-\fB[\fP\fInumber\fP\fB]\fP \fIflag status command\fP
-.RE
-where
-.IP "\ \fInumber\fP"
-is the job-number of the job.
-.IP "\ \fIflag\fP"
-is \fB+\fP or \fB-\fP if the job is the \fB%+\fP or \fB%-\fP job,
-respectively, or space if it is neither.
-.IP "\ \fIstatus\fP"
-indicates the current state of the job and can be
-.RS
-.IP "\fBRunning\fP"
-the job has neither stopped or exited (note that running does not
-necessarily mean consuming CPU time \(em the process could be blocked waiting
-for some event).
-.IP "\fBDone\fP [\fB(\fP\fInumber\fP\fB)\fP]"
-the job exited. \fInumber\fP is the exit status of the job, which is
-omitted if the status is zero.
-.IP "\fBStopped\fP [\fB(\fP\fIsignal\fP\fB)\fP]"
-the job was stopped by the indicated \fIsignal\fP (if no signal is given,
-the job was stopped by SIGTSTP).
-.IP "\fIsignal-description\fP [\fB(core dumped)\fP]"
-the job was killed by a signal (\fIe.g.\fP, Memory\ fault,
-Hangup, \fIetc.\fP \(em use
-\fBkill \-l\fP for a list of signal descriptions).
-The \fB(core\ dumped)\fP message indicates the process created a core file.
-.RE
-.IP "\ \fIcommand\fP"
-is the command that created the process.
-If there are multiple processes in the job, then each process will
-have a line showing its \fIcommand\fP and possibly its \fIstatus\fP,
-if it is different from the status of the previous process.
-.PP
-When an attempt is made to exit the shell while there are jobs in
-the stopped state, the shell warns the user that there are stopped jobs
-and does not exit.
-If another attempt is immediately made to exit the shell, the stopped
-jobs are sent a \fBHUP\fP signal and the shell exits.
-Similarly, if the \fBnohup\fP option is not set and there are running
-jobs when an attempt is made to exit a login shell, the shell warns the
-user and does not exit.
-If another attempt is immediately made to exit the shell, the running
-jobs are sent a \fBHUP\fP signal and the shell exits.
-.\"}}}
-.\"{{{ Emacs Interactive Input Line Editing
-.\"}}}
-.\"{{{ Vi Interactive Input Line Editing
-.\"}}}
-.\"}}}
-.\"{{{ Files
-.SH FILES
-~/.profile
-.br
-/etc/profile
-.br
-/etc/suid_profile
-.\"}}}
-.\"{{{ Notes
-.SH NOTES
-Sh is implemented as a runtime option of pdksh, with only those ksh features
-whose syntax or semantics are incompatible with a traditional Bourne
-shell disabled. Since this leaves some ksh extensions exposed, caution
-should be used where backwards compatibility with traditional Bourne or
-POSIX compliant shells is an issue.
-.\"}}}
-.\"{{{ Bugs
-.SH BUGS
-Any bugs in pdksh should be reported to pdksh@cs.mun.ca. Please
-include the version of pdksh (echo $KSH_VERSION shows it), the machine,
-operating system and compiler you are using and a description of how to
-repeat the bug (a small shell script that demonstrates the bug is
-best). The following, if relevant (if you are not sure, include them),
-can also helpful: options you are using (both options.h options and set
-\-o options) and a copy of your config.h (the file generated by the
-configure script). New versions of pdksh can be obtained from
-ftp.cs.mun.ca:pub/pdksh/.
-.\"}}}
-.\"{{{ Authors
-.SH AUTHORS
-This shell is based on the public domain 7th edition Bourne shell clone by
-Charles Forsyth and parts of the BRL shell by Doug A.\& Gwyn, Doug Kingston,
-Ron Natalie, Arnold Robbins, Lou Salkind and others. The first release
-was created by Eric Gisin, and it was subsequently maintained by
-John R.\& MacMillan (chance!john@sq.sq.com), and
-Simon J.\& Gerraty (sjg@zen.void.oz.au). The current maintainer is
-Michael Rendell (michael@cs.mun.ca).
-The CONTRIBUTORS file in the source distribution contains a more complete
-list of people and their part in the shell's development.
-.\"}}}
-.\"{{{ See also
-.SH "SEE ALSO"
-awk(1),
-ksh(1),
-csh(1), ed(1), getconf(1), getopt(1), sed(1), stty(1), vi(1),
-dup(2), execve(2), getgid(2), getuid(2), open(2), pipe(2), wait(2),
-getopt(3), rand(3), signal(3), system(3),
-environ(5)
-.PP
-.IR "The KornShell Command and Programming Language" ,
-Morris Bolsky and David Korn, 1989, ISBN 0-13-516972-0.
-.PP
-.\" XXX ISBN missing
-.IR "UNIX Shell Programming" ,
-Stephen G.\& Kochan, Patrick H.\& Wood, Hayden.
-.PP
-.IR "IEEE Standard for information Technology \- Portable Operating System Interface (POSIX) \- Part 2: Shell and Utilities" ,
-IEEE Inc, 1993, ISBN 1-55937-255-9.
-.\"}}}
diff --git a/bin/pdksh/sh.h b/bin/pdksh/sh.h
deleted file mode 100644
index 588abd2c18e..00000000000
--- a/bin/pdksh/sh.h
+++ /dev/null
@@ -1,707 +0,0 @@
-/* $OpenBSD: sh.h,v 1.5 1997/01/02 09:34:10 downsj Exp $ */
-
-/*
- * Public Domain Bourne/Korn shell
- */
-
-/* $From: sh.h,v 1.2 1994/05/19 18:32:40 michael Exp michael $ */
-
-#include "config.h" /* system and option configuration info */
-
-#ifdef HAVE_PROTOTYPES
-# define ARGS(args) args /* prototype declaration */
-#else
-# define ARGS(args) () /* K&R declaration */
-#endif
-
-
-/* Start of common headers */
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <setjmp.h>
-#ifdef HAVE_STDDEF_H
-# include <stddef.h>
-#endif
-
-#ifdef HAVE_STDLIB_H
-# include <stdlib.h>
-#else
-/* just a useful subset of what stdlib.h would have */
-extern char * getenv ARGS((const char *));
-extern void * malloc ARGS((size_t));
-extern int free ARGS((void *));
-extern int exit ARGS((int));
-extern int rand ARGS((void));
-extern void srand ARGS((unsigned int));
-extern int atoi ARGS((const char *));
-#endif /* HAVE_STDLIB_H */
-
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#else
-/* just a useful subset of what unistd.h would have */
-extern int access ARGS((const char *, int));
-extern int open ARGS((const char *, int, ...));
-extern int creat ARGS((const char *, mode_t));
-extern int read ARGS((int, char *, unsigned));
-extern int write ARGS((int, const char *, unsigned));
-extern off_t lseek ARGS((int, off_t, int));
-extern int close ARGS((int));
-extern int pipe ARGS((int []));
-extern int dup2 ARGS((int, int));
-extern int unlink ARGS((const char *));
-extern int fork ARGS((void));
-extern int execve ARGS((const char *, char * const[], char * const[]));
-extern int chdir ARGS((const char *));
-extern int kill ARGS((pid_t, int));
-extern char *getcwd(); /* no ARGS here - differs on different machines */
-extern int geteuid ARGS((void));
-extern int readlink ARGS((const char *, char *, int));
-extern int getegid ARGS((void));
-extern int getpid ARGS((void));
-extern int getppid ARGS((void));
-extern unsigned int sleep ARGS((unsigned int));
-extern int isatty ARGS((int));
-# ifdef POSIX_PGRP
-extern int getpgrp ARGS((void));
-extern int setpgid ARGS((pid_t, pid_t));
-# endif /* POSIX_PGRP */
-# ifdef BSD_PGRP
-extern int getpgrp ARGS((pid_t));
-extern int setpgrp ARGS((pid_t, pid_t));
-# endif /* BSD_PGRP */
-# ifdef SYSV_PGRP
-extern int getpgrp ARGS((void));
-extern int setpgrp ARGS((void));
-# endif /* SYSV_PGRP */
-#endif /* HAVE_UNISTD_H */
-
-#ifdef HAVE_STRING_H
-# include <string.h>
-#else
-# include <strings.h>
-# define strchr index
-# define strrchr rindex
-#endif /* HAVE_STRING_H */
-#ifndef HAVE_STRSTR
-char *strstr ARGS((const char *s, const char *p));
-#endif /* HAVE_STRSTR */
-#ifndef HAVE_STRCASECMP
-int strcasecmp ARGS((const char *s1, const char *s2));
-int strncasecmp ARGS((const char *s1, const char *s2, int n));
-#endif /* HAVE_STRCASECMP */
-
-#ifdef HAVE_MEMORY_H
-# include <memory.h>
-#endif
-#ifndef HAVE_MEMSET
-# define memcpy(d, s, n) bcopy(s, d, n)
-# define memcmp(s1, s2, n) bcmp(s1, s2, n)
-void *memset ARGS((void *d, int c, size_t n));
-#endif /* HAVE_MEMSET */
-#ifndef HAVE_MEMMOVE
-# ifdef HAVE_BCOPY
-# define memmove(d, s, n) bcopy(s, d, n)
-# else
-void *memmove ARGS((void *d, const void *s, size_t n));
-# endif
-#endif /* HAVE_MEMMOVE */
-
-#ifdef HAVE_PROTOTYPES
-# include <stdarg.h>
-# define SH_VA_START(va, argn) va_start(va, argn)
-#else
-# include <varargs.h>
-# define SH_VA_START(va, argn) va_start(va)
-#endif /* HAVE_PROTOTYPES */
-
-#include <errno.h>
-extern int errno;
-
-#ifdef HAVE_FCNTL_H
-# include <fcntl.h>
-#else
-# include <sys/file.h>
-#endif /* HAVE_FCNTL_H */
-#ifndef O_ACCMODE
-# define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR)
-#endif /* !O_ACCMODE */
-
-#ifndef F_OK /* access() arguments */
-# define F_OK 0
-# define X_OK 1
-# define W_OK 2
-# define R_OK 4
-#endif /* !F_OK */
-
-#ifndef SEEK_SET
-# ifdef L_SET
-# define SEEK_SET L_SET
-# define SEEK_CUR L_INCR
-# define SEEK_END L_XTND
-# else /* L_SET */
-# define SEEK_SET 0
-# define SEEK_CUR 1
-# define SEEK_END 2
-# endif /* L_SET */
-#endif /* !SEEK_SET */
-
-/* Some machines (eg, FreeBSD 1.1.5) define CLK_TCK in limits.h
- * (ksh_limval.h assumes limits has been included, if available)
- */
-#ifdef HAVE_LIMITS_H
-# include <limits.h>
-#endif /* HAVE_LIMITS_H */
-
-#include <signal.h>
-#ifdef NSIG
-# define SIGNALS NSIG
-#else
-# ifdef _MINIX
-# define SIGNALS (_NSIG+1) /* _NSIG is # of signals used, excluding 0. */
-# else
-# ifdef _SIGMAX /* QNX */
-# define SIGNALS _SIGMAX
-# else /* _SIGMAX */
-# define SIGNALS 32
-# endif /* _SIGMAX */
-# endif /* _MINIX */
-#endif /* NSIG */
-#ifndef SIGCHLD
-# define SIGCHLD SIGCLD
-#endif
-/* struct sigaction.sa_flags is set to KSH_SA_FLAGS. Used to ensure
- * system calls are interrupted
- */
-#ifdef SA_INTERRUPT
-# define KSH_SA_FLAGS SA_INTERRUPT
-#else /* SA_INTERRUPT */
-# define KSH_SA_FLAGS 0
-#endif /* SA_INTERRUPT */
-
-typedef RETSIGTYPE (*handler_t) ARGS((int)); /* signal handler */
-
-#ifdef USE_FAKE_SIGACT
-# include "sigact.h" /* use sjg's fake sigaction() */
-#endif
-
-#ifdef HAVE_PATHS_H
-# include <paths.h>
-#endif /* HAVE_PATHS_H */
-#ifdef _PATH_DEFPATH
-# define DEFAULT__PATH _PATH_DEFPATH
-#else /* _PATH_DEFPATH */
-# define DEFAULT__PATH DEFAULT_PATH
-#endif /* _PATH_DEFPATH */
-
-#ifndef offsetof
-# define offsetof(type,id) ((size_t)&((type*)NULL)->id)
-#endif
-
-#ifndef HAVE_KILLPG
-# define killpg(p, s) kill(-(p), (s))
-#endif /* !HAVE_KILLPG */
-
-/* Special cases for execve(2) */
-#ifdef OS2
-extern int ksh_execve(char *cmd, char **args, char **env);
-#else /* OS2 */
-# if defined(OS_ISC) && defined(_POSIX_SOURCE)
-/* Kludge for ISC 3.2 (and other versions?) so programs will run correctly. */
-# define ksh_execve(p, av, ev) do { \
- __setostype(0); \
- execve(p, av, ev); \
- __setostype(1); \
- } while (0)
-# else /* OS_ISC && _POSIX */
-# define ksh_execve(p, av, ev) execve(p, av, ev)
-# endif /* OS_ISC && _POSIX */
-#endif /* OS2 */
-
-/* this is a hang-over from older versions of the os2 port */
-#define ksh_dupbase(fd, base) fcntl(fd, F_DUPFD, base)
-
-#ifdef HAVE_SIGSETJMP
-# define ksh_sigsetjmp(env,sm) sigsetjmp((env), (sm))
-# define ksh_siglongjmp(env,v) siglongjmp((env), (v))
-# define ksh_jmp_buf sigjmp_buf
-#else /* HAVE_SIGSETJMP */
-# ifdef HAVE__SETJMP
-# define ksh_sigsetjmp(env,sm) _setjmp(env)
-# define ksh_siglongjmp(env,v) _longjmp((env), (v))
-# else /* HAVE__SETJMP */
-# define ksh_sigsetjmp(env,sm) setjmp(env)
-# define ksh_siglongjmp(env,v) longjmp((env), (v))
-# endif /* HAVE__SETJMP */
-# define ksh_jmp_buf jmp_buf
-#endif /* HAVE_SIGSETJMP */
-
-/* Find a integer type that is at least 32 bits (or die) - SIZEOF_* defined
- * by autoconf (assumes an 8 bit byte, but I'm not concerned)
- */
-#if SIZEOF_INT >= 4
-# define INT32 int
-#else /* SIZEOF_INT */
-# if SIZEOF_LONG >= 4
-# define INT32 long
-# else /* SIZEOF_LONG */
- #error cannot find 32 bit type...
-# endif /* SIZEOF_LONG */
-#endif /* SIZEOF_INT */
-
-/* end of common headers */
-
-/* Stop gcc and lint from complaining about possibly uninitialized variables */
-#if defined(__GNUC__) || defined(lint)
-# define UNINITIALIZED(var) var = 0
-#else
-# define UNINITIALIZED(var) var
-#endif /* GNUC || lint */
-
-/* some useful #defines */
-#ifdef EXTERN
-# define I__(i) = i
-#else
-# define I__(i)
-# define EXTERN extern
-# define EXTERN_DEFINED
-#endif
-
-#ifndef EXECSHELL
-/* shell to exec scripts (see also $SHELL initialization in main.c) */
-# ifdef OS2
-# define EXECSHELL "c:\\os2\\cmd.exe"
-# define EXECSHELL_STR "OS2_SHELL"
-# else /* OS2 */
-# define EXECSHELL "/bin/sh"
-# define EXECSHELL_STR "EXECSHELL"
-# endif /* OS2 */
-#endif
-
-/* ISABSPATH() means path is fully and completely specified,
- * ISROOTEDPATH() means a .. as the first component is a no-op,
- * ISRELPATH() means $PWD can be tacked on to get an absolute path.
- *
- * OS Path ISABSPATH ISROOTEDPATH ISRELPATH
- * unix /foo yes yes no
- * unix foo no no yes
- * unix ../foo no no yes
- * os2 a:/foo yes yes no
- * os2 a:foo no no no
- * os2 /foo no yes no
- * os2 foo no no yes
- * os2 ../foo no no yes
- */
-#ifdef OS2
-# define PATHSEP ';'
-# define DIRSEP '/' /* even though \ is native */
-# define DIRSEPSTR "\\"
-# define ISDIRSEP(c) ((c) == '\\' || (c) == '/')
-# define ISABSPATH(s) (((s)[0] && (s)[1] == ':' && ISDIRSEP((s)[2])))
-# define ISROOTEDPATH(s) (ISDIRSEP((s)[0]) || ISABSPATH(s))
-# define ISRELPATH(s) (!(s)[0] || ((s)[1] != ':' && !ISDIRSEP((s)[0])))
-# define FILECHCONV(c) (isascii(c) && isupper(c) ? tolower(c) : c)
-# define FILECMP(s1, s2) stricmp(s1, s2)
-# define FILENCMP(s1, s2, n) strnicmp(s1, s2, n)
-extern char *ksh_strchr_dirsep(const char *path);
-extern char *ksh_strrchr_dirsep(const char *path);
-# define chdir _chdir2
-# define getcwd _getcwd2
-#else
-# define PATHSEP ':'
-# define DIRSEP '/'
-# define DIRSEPSTR "/"
-# define ISDIRSEP(c) ((c) == '/')
-# define ISABSPATH(s) ISDIRSEP((s)[0])
-# define ISROOTEDPATH(s) ISABSPATH(s)
-# define ISRELPATH(s) (!ISABSPATH(s))
-# define FILECHCONV(c) c
-# define FILECMP(s1, s2) strcmp(s1, s2)
-# define FILENCMP(s1, s2, n) strncmp(s1, s2, n)
-# define ksh_strchr_dirsep(p) strchr(p, DIRSEP)
-# define ksh_strrchr_dirsep(p) strrchr(p, DIRSEP)
-#endif
-
-typedef int bool_t;
-#define FALSE 0
-#define TRUE 1
-
-#define NELEM(a) (sizeof(a) / sizeof((a)[0]))
-#define sizeofN(type, n) (sizeof(type) * (n))
-#define BIT(i) (1<<(i)) /* define bit in flag */
-
-/* Table flag type - needs > 16 and < 32 bits */
-typedef INT32 Tflag;
-
-#define NUFILE 32 /* Number of user-accessible files */
-#define FDBASE 10 /* First file usable by Shell */
-
-/* you're not going to run setuid shell scripts, are you? */
-#define eaccess(path, mode) access(path, mode)
-
-/* Make MAGIC a char that might be printed to make bugs more obvious, but
- * not a char that is used often. Also, can't use the high bit as it causes
- * portability problems (calling strchr(x, 0x80|'x') is error prone).
- */
-#define MAGIC (7)/* prefix for *?[!{,} during expand */
-#define ISMAGIC(c) ((unsigned char)(c) == MAGIC)
-#define NOT '!' /* might use ^ (ie, [!...] vs [^..]) */
-
-#define LINE 1024 /* input line size */
-#define PATH 1024 /* pathname size (todo: PATH_MAX/pathconf()) */
-#define ARRAYMAX 1023 /* max array index */
-
-EXTERN const char *kshname; /* $0 */
-EXTERN pid_t kshpid; /* $$, shell pid */
-EXTERN pid_t procpid; /* pid of executing process */
-EXTERN int exstat; /* exit status */
-EXTERN int subst_exstat; /* exit status of last $(..)/`..` */
-EXTERN const char *safe_prompt; /* safe prompt if PS1 substitution fails */
-
-
-/*
- * Area-based allocation built on malloc/free
- */
-
-typedef struct Area {
- struct Block *freelist; /* free list */
-} Area;
-
-EXTERN Area aperm; /* permanent object space */
-#define APERM &aperm
-#define ATEMP &e->area
-
-#ifdef MEM_DEBUG
-# include "chmem.h" /* a debugging front end for malloc et. al. */
-#endif /* MEM_DEBUG */
-
-
-/*
- * parsing & execution environment
- */
-EXTERN struct env {
- short type; /* enviroment type - see below */
- short flags; /* EF_* */
- Area area; /* temporary allocation area */
- struct block *loc; /* local variables and functions */
- short *savefd; /* original redirected fd's */
- struct env *oenv; /* link to previous enviroment */
- ksh_jmp_buf jbuf; /* long jump back to env creator */
- struct temp *temps; /* temp files */
-} *e;
-
-/* struct env.type values */
-#define E_NONE 0 /* dummy enviroment */
-#define E_PARSE 1 /* parsing command # */
-#define E_FUNC 2 /* executing function # */
-#define E_INCL 3 /* including a file via . # */
-#define E_EXEC 4 /* executing command tree */
-#define E_LOOP 5 /* executing for/while # */
-#define E_ERRH 6 /* general error handler # */
-/* # indicates env has valid jbuf (see unwind()) */
-
-/* struct env.flag values */
-#define EF_FUNC_PARSE BIT(0) /* function being parsed */
-#define EF_BRKCONT_PASS BIT(1) /* set if E_LOOP must pass break/continue on */
-
-/* Do breaks/continues stop at env type e? */
-#define STOP_BRKCONT(t) ((t) == E_NONE || (t) == E_PARSE \
- || (t) == E_FUNC || (t) == E_INCL)
-/* Do returns stop at env type e? */
-#define STOP_RETURN(t) ((t) == E_FUNC || (t) == E_INCL)
-
-/* values for ksh_siglongjmp(e->jbuf, 0) */
-#define LRETURN 1 /* return statement */
-#define LEXIT 2 /* exit statement */
-#define LERROR 3 /* errorf() called */
-#define LLEAVE 4 /* untrappable exit/error */
-#define LINTR 5 /* ^C noticed */
-#define LBREAK 6 /* break statement */
-#define LCONTIN 7 /* continue statement */
-#define LSHELL 8 /* return to interactive shell() */
-#define LAEXPR 9 /* error in arithmetic expression */
-
-
-/* option processing */
-#define OF_CMDLINE 0x01 /* command line */
-#define OF_SET 0x02 /* set builtin */
-#define OF_SPECIAL 0x04 /* a special variable changing */
-#define OF_ANY (OF_CMDLINE | OF_SET | OF_SPECIAL)
-
-struct option {
- const char *name; /* long name of option */
- char c; /* character flag (if any) */
- short flags; /* OF_* */
-};
-extern const struct option options[];
-
-/*
- * flags (the order of these enums MUST match the order in misc.c(options[]))
- */
-enum sh_flag {
- FEXPORT = 0, /* -a: export all */
-#ifdef BRACE_EXPAND
- FBRACEEXPAND, /* enable {} globbing */
-#endif
- FBGNICE, /* bgnice */
- FCOMMAND, /* -c: (invocation) execute specified command */
-#ifdef EMACS
- FEMACS, /* emacs command editing */
-#endif
- FERREXIT, /* -e: quit on error */
-#ifdef EMACS
- FGMACS, /* gmacs command editing */
-#endif
- FIGNOREEOF, /* eof does not exit */
- FTALKING, /* -i: interactive */
- FKEYWORD, /* -k: name=value anywere */
- FLOGIN, /* -l: a login shell */
- FMARKDIRS, /* mark dirs with / in file name completion */
- FMONITOR, /* -m: job control monitoring */
- FNOCLOBBER, /* -C: don't overwrite existing files */
- FNOEXEC, /* -n: don't execute any commands */
- FNOGLOB, /* -f: don't do file globbing */
- FNOHUP, /* -H: don't kill running jobs when login shell exits */
- FNOLOG, /* don't save functions in history (ignored) */
-#ifdef JOBS
- FNOTIFY, /* -b: asynchronous job completion notification */
-#endif
- FNOUNSET, /* -u: using an unset var is an error */
- FPHYSICAL, /* -o physical: don't do logical cd's/pwd's */
- FPOSIX, /* -o posix: be posixly correct */
- FPRIVILEGED, /* -p: use suid_profile */
- FRESTRICTED, /* -r: restricted shell */
- FSH, /* -o sh: favor sh behavour */
- FSTDIN, /* -s: (invocation) parse stdin */
- FTRACKALL, /* -h: create tracked aliases for all commands */
- FVERBOSE, /* -v: echo input */
-#ifdef VI
- FVI, /* vi command editing */
- FVIRAW, /* always read in raw mode (ignored) */
- FVISHOW8, /* display chars with 8th bit set as is (versus M-) */
- FVITABCOMPLETE, /* enable tab as file name completion char */
- FVIESCCOMPLETE, /* enable ESC as file name completion in command mode */
-#endif
- FXTRACE, /* -x: execution trace */
- FNFLAGS /* (place holder: how many flags are there) */
-};
-
-#define Flag(f) (shell_flags[(int) (f)])
-
-EXTERN char shell_flags [FNFLAGS];
-
-EXTERN char null [] I__(""); /* null value for variable */
-EXTERN char space [] I__(" ");
-EXTERN char newline [] I__("\n");
-EXTERN char slash [] I__("/");
-
-/* temp/here files. the file is removed when the struct is freed */
-struct temp {
- struct temp *next;
- struct shf *shf;
- int pid; /* pid of process parsed here-doc */
- char *name;
-};
-
-/* here documents in functions are treated specially (the get removed when
- * shell exis) */
-EXTERN struct temp *func_heredocs;
-
-/*
- * stdio and our IO routines
- */
-
-#define shl_spare (&shf_iob[0]) /* for c_read()/c_print() */
-#define shl_stdout (&shf_iob[1])
-#define shl_out (&shf_iob[2])
-EXTERN int shl_stdout_ok;
-
-/*
- * trap handlers
- */
-typedef struct trap {
- int signal; /* signal number */
- const char *name; /* short name */
- const char *mess; /* descriptive name */
- char *trap; /* trap command */
- int volatile set; /* trap pending */
- int flags; /* TF_* */
- handler_t cursig; /* current handler (valid if TF_ORIG_* set) */
- handler_t shtrap; /* shell signal handler */
-} Trap;
-
-/* values for Trap.flags */
-#define TF_SHELL_USES BIT(0) /* shell uses signal, user can't change */
-#define TF_USER_SET BIT(1) /* user has (tried to) set trap */
-#define TF_ORIG_IGN BIT(2) /* original action was SIG_IGN */
-#define TF_ORIG_DFL BIT(3) /* original action was SIG_DFL */
-#define TF_EXEC_IGN BIT(4) /* restore SIG_IGN just before exec */
-#define TF_EXEC_DFL BIT(5) /* restore SIG_DFL just before exec */
-#define TF_DFL_INTR BIT(6) /* when received, default action is LINTR */
-#define TF_TTY_INTR BIT(7) /* tty generated signal (see j_waitj) */
-#define TF_CHANGED BIT(8) /* used by runtrap() to detect trap changes */
-#define TF_FATAL BIT(9) /* causes termination if not trapped */
-
-/* values for setsig()/setexecsig() flags argument */
-#define SS_RESTORE_MASK 0x3 /* how to restore a signal before an exec() */
-#define SS_RESTORE_CURR 0 /* leave current handler in place */
-#define SS_RESTORE_ORIG 1 /* restore original handler */
-#define SS_RESTORE_DFL 2 /* restore to SIG_DFL */
-#define SS_RESTORE_IGN 3 /* restore to SIG_IGN */
-#define SS_FORCE BIT(3) /* set signal even if original signal ignored */
-#define SS_USER BIT(4) /* user is doing the set (ie, trap command) */
-#define SS_SHTRAP BIT(5) /* trap for internal use (CHLD,ALRM,WINCH) */
-
-#define SIGEXIT_ 0 /* for trap EXIT */
-#define SIGERR_ SIGNALS /* for trap ERR */
-
-EXTERN int volatile trap; /* traps pending? */
-EXTERN int volatile intrsig; /* pending trap interrupts executing command */
-EXTERN int volatile fatal_trap;/* received a fatal signal */
-#ifndef FROM_TRAP_C
-/* Kludge to avoid bogus re-declaration of sigtraps[] error on AIX 3.2.5 */
-extern Trap sigtraps[SIGNALS+1];
-#endif /* !FROM_TRAP_C */
-
-
-#ifdef KSH
-/*
- * TMOUT support
- */
-/* values for ksh_tmout_state */
-enum tmout_enum {
- TMOUT_EXECUTING = 0, /* executing commands */
- TMOUT_READING, /* waiting for input */
- TMOUT_LEAVING /* have timed out */
- };
-EXTERN unsigned int ksh_tmout;
-EXTERN enum tmout_enum ksh_tmout_state I__(TMOUT_EXECUTING);
-#endif /* KSH */
-
-
-/* For "You have stopped jobs" message */
-EXTERN int really_exit;
-
-
-/*
- * fast character classes
- */
-#define C_ALPHA BIT(0) /* a-z_A-Z */
-#define C_DIGIT BIT(1) /* 0-9 */
-#define C_LEX1 BIT(2) /* \0 \t\n|&;<>() */
-#define C_VAR1 BIT(3) /* *@#!$-? */
-#define C_IFSWS BIT(4) /* \t \n (IFS white space) */
-#define C_SUBOP1 BIT(5) /* "=-+?" */
-#define C_SUBOP2 BIT(6) /* "#%" */
-#define C_IFS BIT(7) /* $IFS */
-#define C_QUOTE BIT(8) /* \n\t"#$&'()*;<>?[\`| (needing quoting) */
-
-extern short ctypes [];
-
-#define ctype(c, t) !!(ctypes[(unsigned char)(c)]&(t))
-#define letter(c) ctype(c, C_ALPHA)
-#define digit(c) ctype(c, C_DIGIT)
-#define letnum(c) ctype(c, C_ALPHA|C_DIGIT)
-
-EXTERN int ifs0 I__(' '); /* for "$*" */
-
-
-/* Argument parsing for built-in commands and getopts command */
-
-/* Values for Getopt.flags */
-#define GF_ERROR BIT(0) /* call errorf() if there is an error */
-#define GF_PLUSOPT BIT(1) /* allow +c as an option */
-#define GF_NONAME BIT(2) /* don't print argv[0] in errors */
-
-/* Values for Getopt.info */
-#define GI_MINUS BIT(0) /* an option started with -... */
-#define GI_PLUS BIT(1) /* an option started with +... */
-#define GI_MINUSMINUS BIT(2) /* arguments were ended with -- */
-
-typedef struct {
- int optind;
- char *optarg;
- int flags; /* see GF_* */
- int info; /* see GI_* */
- unsigned int p; /* 0 or index into argv[optind - 1] */
- char buf[2]; /* for bad option OPTARG value */
-} Getopt;
-
-EXTERN Getopt builtin_opt; /* for shell builtin commands */
-
-
-#ifdef KSH
-/* This for co-processes */
-
-typedef INT32 Coproc_id; /* something that won't (realisticly) wrap */
-struct coproc {
- int read; /* pipe from co-process's stdout */
- int readw; /* other side of read (saved temporarily) */
- int write; /* pipe to co-process's stdin */
- Coproc_id id; /* id of current output pipe */
- int njobs; /* number of live jobs using output pipe */
- void *job; /* 0 or job of co-process using input pipe */
-};
-EXTERN struct coproc coproc;
-#endif /* KSH */
-
-/* Used in jobs.c and by coprocess stuff in exec.c */
-#ifdef JOB_SIGS
-EXTERN sigset_t sm_default, sm_sigchld;
-#endif /* JOB_SIGS */
-
-extern const char ksh_version[];
-
-/* name of called builtin function (used by error functions) */
-EXTERN char *builtin_argv0;
-EXTERN Tflag builtin_flag; /* flags of called builtin (SPEC_BI, etc.) */
-
-/* current working directory, and size of memory allocated for same */
-EXTERN char *current_wd;
-EXTERN int current_wd_size;
-
-#ifdef EDIT
-/* Minimium required space to work with on a line - if the prompt leaves less
- * space than this on a line, the prompt is truncated.
- */
-# define MIN_EDIT_SPACE 7
-/* Minimium allowed value for x_cols: 2 for prompt, 3 for " < " at end of line
- */
-# define MIN_COLS (2 + MIN_EDIT_SPACE + 3)
-EXTERN int x_cols I__(80); /* tty columns */
-#else
-# define x_cols 80 /* for pr_menu(exec.c) */
-#endif
-
-
-/* These to avoid bracket matching problems */
-#define OPAREN '('
-#define CPAREN ')'
-#define OBRACK '['
-#define CBRACK ']'
-#define OBRACE '{'
-#define CBRACE '}'
-
-/* Determine the location of the system (common) profile */
-#ifndef KSH_SYSTEM_PROFILE
-# ifdef __NeXT
-# define KSH_SYSTEM_PROFILE "/etc/profile.std"
-# else /* __NeXT */
-# define KSH_SYSTEM_PROFILE "/etc/profile"
-# endif /* __NeXT */
-#endif /* KSH_SYSTEM_PROFILE */
-
-#include "shf.h"
-#include "table.h"
-#include "tree.h"
-#include "expand.h"
-#include "lex.h"
-#include "proto.h"
-
-/* be sure not to interfere with anyone else's idea about EXTERN */
-#ifdef EXTERN_DEFINED
-# undef EXTERN_DEFINED
-# undef EXTERN
-#endif
-#undef I__
diff --git a/bin/pdksh/shf.c b/bin/pdksh/shf.c
deleted file mode 100644
index 78266aa9b26..00000000000
--- a/bin/pdksh/shf.c
+++ /dev/null
@@ -1,1271 +0,0 @@
-/* $OpenBSD: shf.c,v 1.3 1997/06/19 13:58:46 kstailey Exp $ */
-
-/*
- * Shell file I/O routines
- */
-
-#include "sh.h"
-#include "ksh_stat.h"
-#include "ksh_limval.h"
-
-
-/* flags to shf_emptybuf() */
-#define EB_READSW 0x01 /* about to switch to reading */
-#define EB_GROW 0x02 /* grow buffer if necessary (STRING+DYNAMIC) */
-
-/*
- * Replacement stdio routines. Stdio is too flakey on too many machines
- * to be useful when you have multiple processes using the same underlying
- * file descriptors.
- */
-
-static int shf_fillbuf ARGS((struct shf *shf));
-static int shf_emptybuf ARGS((struct shf *shf, int flags));
-
-/* Open a file. First three args are for open(), last arg is flags for
- * this package. Returns NULL if file could not be opened, or if a dup
- * fails.
- */
-struct shf *
-shf_open(name, oflags, mode, sflags)
- const char *name;
- int oflags;
- int mode;
- int sflags;
-{
- int fd;
-
- fd = open(name, oflags, mode);
- if (fd < 0)
- return NULL;
- if ((sflags & SHF_MAPHI) && fd < FDBASE) {
- int nfd;
-
- nfd = ksh_dupbase(fd, FDBASE);
- close(fd);
- if (nfd < 0)
- return NULL;
- fd = nfd;
- }
- sflags &= ~SHF_ACCMODE;
- sflags |= (oflags & O_ACCMODE) == O_RDONLY ? SHF_RD
- : ((oflags & O_ACCMODE) == O_WRONLY ? SHF_WR
- : SHF_RDWR);
-
- return shf_fdopen(fd, sflags, (struct shf *) 0);
-}
-
-/* Set up the shf structure for a file descriptor. Doesn't fail. */
-struct shf *
-shf_fdopen(fd, sflags, shf)
- int fd;
- int sflags;
- struct shf *shf;
-{
- int bsize = sflags & SHF_UNBUF ? (sflags & SHF_RD ? 1 : 0) : SHF_BSIZE;
-
- /* use fcntl() to figure out correct read/write flags */
- if (sflags & SHF_GETFL) {
- int flags = fcntl(fd, F_GETFL, 0);
-
- if (flags < 0)
- /* will get an error on first read/write */
- sflags |= SHF_RDWR;
- else
- switch (flags & O_ACCMODE) {
- case O_RDONLY: sflags |= SHF_RD; break;
- case O_WRONLY: sflags |= SHF_WR; break;
- case O_RDWR: sflags |= SHF_RDWR; break;
- }
- }
-
- if (!(sflags & (SHF_RD | SHF_WR)))
- internal_errorf(1, "shf_fdopen: missing read/write");
-
- if (shf) {
- if (bsize) {
- shf->buf = (unsigned char *) alloc(bsize, ATEMP);
- sflags |= SHF_ALLOCB;
- } else
- shf->buf = (unsigned char *) 0;
- } else {
- shf = (struct shf *) alloc(sizeof(struct shf) + bsize, ATEMP);
- shf->buf = (unsigned char *) &shf[1];
- sflags |= SHF_ALLOCS;
- }
- shf->areap = ATEMP;
- shf->fd = fd;
- shf->rp = shf->wp = shf->buf;
- shf->rnleft = 0;
- shf->rbsize = bsize;
- shf->wnleft = 0; /* force call to shf_emptybuf() */
- shf->wbsize = sflags & SHF_UNBUF ? 0 : bsize;
- shf->flags = sflags;
- shf->errno_ = 0;
- shf->bsize = bsize;
- if (sflags & SHF_CLEXEC)
- fd_clexec(fd);
- return shf;
-}
-
-/* Set up an existing shf (and buffer) to use the given fd */
-struct shf *
-shf_reopen(fd, sflags, shf)
- int fd;
- int sflags;
- struct shf *shf;
-{
- int bsize = sflags & SHF_UNBUF ? (sflags & SHF_RD ? 1 : 0) : SHF_BSIZE;
-
- /* use fcntl() to figure out correct read/write flags */
- if (sflags & SHF_GETFL) {
- int flags = fcntl(fd, F_GETFL, 0);
-
- if (flags < 0)
- /* will get an error on first read/write */
- sflags |= SHF_RDWR;
- else
- switch (flags & O_ACCMODE) {
- case O_RDONLY: sflags |= SHF_RD; break;
- case O_WRONLY: sflags |= SHF_WR; break;
- case O_RDWR: sflags |= SHF_RDWR; break;
- }
- }
-
- if (!(sflags & (SHF_RD | SHF_WR)))
- internal_errorf(1, "shf_reopen: missing read/write");
- if (!shf || !shf->buf || shf->bsize < bsize)
- internal_errorf(1, "shf_reopen: bad shf/buf/bsize");
-
- /* assumes shf->buf and shf->bsize already set up */
- shf->fd = fd;
- shf->rp = shf->wp = shf->buf;
- shf->rnleft = 0;
- shf->rbsize = bsize;
- shf->wnleft = 0; /* force call to shf_emptybuf() */
- shf->wbsize = sflags & SHF_UNBUF ? 0 : bsize;
- shf->flags = (shf->flags & (SHF_ALLOCS | SHF_ALLOCB)) | sflags;
- shf->errno_ = 0;
- if (sflags & SHF_CLEXEC)
- fd_clexec(fd);
- return shf;
-}
-
-/* Open a string for reading or writing. If reading, bsize is the number
- * of bytes that can be read. If writing, bsize is the maximum number of
- * bytes that can be written. If shf is not null, it is filled in and
- * returned, if it is null, shf is allocated. If writing and buf is null
- * and SHF_DYNAMIC is set, the buffer is allocated (if bsize > 0, it is
- * used for the initial size). Doesn't fail.
- * When writing, a byte is reserved for a trailing null - see shf_sclose().
- */
-struct shf *
-shf_sopen(buf, bsize, sflags, shf)
- char *buf;
- int bsize;
- int sflags;
- struct shf *shf;
-{
- /* can't have a read+write string */
- if (!(sflags & (SHF_RD | SHF_WR))
- || (sflags & (SHF_RD | SHF_WR)) == (SHF_RD | SHF_WR))
- internal_errorf(1, "shf_sopen: flags 0x%x", sflags);
-
- if (!shf) {
- shf = (struct shf *) alloc(sizeof(struct shf), ATEMP);
- sflags |= SHF_ALLOCS;
- }
- shf->areap = ATEMP;
- if (!buf && (sflags & SHF_WR) && (sflags & SHF_DYNAMIC)) {
- if (bsize <= 0)
- bsize = 64;
- sflags |= SHF_ALLOCB;
- buf = alloc(bsize, shf->areap);
- }
- shf->fd = -1;
- shf->buf = shf->rp = shf->wp = (unsigned char *) buf;
- shf->rnleft = bsize;
- shf->rbsize = bsize;
- shf->wnleft = bsize - 1; /* space for a '\0' */
- shf->wbsize = bsize;
- shf->flags = sflags | SHF_STRING;
- shf->errno_ = 0;
- shf->bsize = bsize;
-
- return shf;
-}
-
-/* Flush and close file descriptor, free the shf structure */
-int
-shf_close(shf)
- struct shf *shf;
-{
- int ret = 0;
-
- if (shf->fd >= 0) {
- ret = shf_flush(shf);
- if (close(shf->fd) < 0)
- ret = EOF;
- }
- if (shf->flags & SHF_ALLOCS)
- afree(shf, shf->areap);
- else if (shf->flags & SHF_ALLOCB)
- afree(shf->buf, shf->areap);
-
- return ret;
-}
-
-/* Flush and close file descriptor, don't free file structure */
-int
-shf_fdclose(shf)
- struct shf *shf;
-{
- int ret = 0;
-
- if (shf->fd >= 0) {
- ret = shf_flush(shf);
- if (close(shf->fd) < 0)
- ret = EOF;
- shf->rnleft = 0;
- shf->rp = shf->buf;
- shf->wnleft = 0;
- shf->fd = -1;
- }
-
- return ret;
-}
-
-/* Close a string - if it was opened for writing, it is null terminated;
- * returns a pointer to the string and frees shf if it was allocated
- * (does not free string if it was allocated).
- */
-char *
-shf_sclose(shf)
- struct shf *shf;
-{
- unsigned char *s = shf->buf;
-
- /* null terminate */
- if (shf->flags & SHF_WR) {
- shf->wnleft++;
- shf_putc('\0', shf);
- }
- if (shf->flags & SHF_ALLOCS)
- afree(shf, shf->areap);
- return (char *) s;
-}
-
-/* Flush and free file structure, don't close file descriptor */
-int
-shf_finish(shf)
- struct shf *shf;
-{
- int ret = 0;
-
- if (shf->fd >= 0)
- ret = shf_flush(shf);
- if (shf->flags & SHF_ALLOCS)
- afree(shf, shf->areap);
- else if (shf->flags & SHF_ALLOCB)
- afree(shf->buf, shf->areap);
-
- return ret;
-}
-
-/* Un-read what has been read but not examined, or write what has been
- * buffered. Returns 0 for success, EOF for (write) error.
- */
-int
-shf_flush(shf)
- struct shf *shf;
-{
- if (shf->flags & SHF_STRING)
- return (shf->flags & SHF_WR) ? EOF : 0;
-
- if (shf->fd < 0)
- internal_errorf(1, "shf_flush: no fd");
-
- if (shf->flags & SHF_ERROR) {
- errno = shf->errno_;
- return EOF;
- }
-
- if (shf->flags & SHF_READING) {
- shf->flags &= ~(SHF_EOF | SHF_READING);
- if (shf->rnleft > 0) {
- lseek(shf->fd, (off_t) -shf->rnleft, 1);
- shf->rnleft = 0;
- shf->rp = shf->buf;
- }
- return 0;
- } else if (shf->flags & SHF_WRITING)
- return shf_emptybuf(shf, 0);
-
- return 0;
-}
-
-/* Write out any buffered data. If currently reading, flushes the read
- * buffer. Returns 0 for success, EOF for (write) error.
- */
-static int
-shf_emptybuf(shf, flags)
- struct shf *shf;
- int flags;
-{
- int ret = 0;
-
- if (!(shf->flags & SHF_STRING) && shf->fd < 0)
- internal_errorf(1, "shf_emptybuf: no fd");
-
- if (shf->flags & SHF_ERROR) {
- errno = shf->errno_;
- return EOF;
- }
-
- if (shf->flags & SHF_READING) {
- if (flags & EB_READSW) /* doesn't happen */
- return 0;
- ret = shf_flush(shf);
- shf->flags &= ~SHF_READING;
- }
- if (shf->flags & SHF_STRING) {
- unsigned char *nbuf;
-
- /* Note that we assume SHF_ALLOCS is not set if SHF_ALLOCB
- * is set... (changing the shf pointer could cause problems)
- */
- if (!(flags & EB_GROW) || !(shf->flags & SHF_DYNAMIC)
- || !(shf->flags & SHF_ALLOCB))
- return EOF;
- /* allocate more space for buffer */
- nbuf = (unsigned char *) aresize(shf->buf, shf->wbsize * 2,
- shf->areap);
- shf->rp = nbuf + (shf->rp - shf->buf);
- shf->wp = nbuf + (shf->wp - shf->buf);
- shf->rbsize += shf->wbsize;
- shf->wbsize += shf->wbsize;
- shf->wnleft += shf->wbsize;
- shf->wbsize *= 2;
- shf->buf = nbuf;
- } else {
- if (shf->flags & SHF_WRITING) {
- int ntowrite = shf->wp - shf->buf;
- unsigned char *buf = shf->buf;
- int n;
-
- while (ntowrite > 0) {
- n = write(shf->fd, buf, ntowrite);
- if (n < 0) {
- if (errno == EINTR
- && !(shf->flags & SHF_INTERRUPT))
- continue;
- shf->flags |= SHF_ERROR;
- shf->errno_ = errno;
- shf->wnleft = 0;
- if (buf != shf->buf) {
- /* allow a second flush
- * to work */
- memmove(shf->buf, buf,
- ntowrite);
- shf->wp = shf->buf + ntowrite;
- }
- return EOF;
- }
- buf += n;
- ntowrite -= n;
- }
- if (flags & EB_READSW) {
- shf->wp = shf->buf;
- shf->wnleft = 0;
- shf->flags &= ~SHF_WRITING;
- return 0;
- }
- }
- shf->wp = shf->buf;
- shf->wnleft = shf->wbsize;
- }
- shf->flags |= SHF_WRITING;
-
- return ret;
-}
-
-/* Fill up a read buffer. Returns EOF for a read error, 0 otherwise. */
-static int
-shf_fillbuf(shf)
- struct shf *shf;
-{
- if (shf->flags & SHF_STRING)
- return 0;
-
- if (shf->fd < 0)
- internal_errorf(1, "shf_fillbuf: no fd");
-
- if (shf->flags & (SHF_EOF | SHF_ERROR)) {
- if (shf->flags & SHF_ERROR)
- errno = shf->errno_;
- return EOF;
- }
-
- if ((shf->flags & SHF_WRITING) && shf_emptybuf(shf, EB_READSW) == EOF)
- return EOF;
-
- shf->flags |= SHF_READING;
-
- shf->rp = shf->buf;
- while (1) {
- shf->rnleft = blocking_read(shf->fd, (char *) shf->buf,
- shf->rbsize);
- if (shf->rnleft < 0 && errno == EINTR
- && !(shf->flags & SHF_INTERRUPT))
- continue;
- break;
- }
- if (shf->rnleft <= 0) {
- if (shf->rnleft < 0) {
- shf->flags |= SHF_ERROR;
- shf->errno_ = errno;
- shf->rnleft = 0;
- shf->rp = shf->buf;
- return EOF;
- }
- shf->flags |= SHF_EOF;
- }
- return 0;
-}
-
-/* Seek to a new position in the file. If writing, flushes the buffer
- * first. If reading, optimizes small relative seeks that stay inside the
- * buffer. Returns 0 for success, EOF otherwise.
- */
-int
-shf_seek(shf, where, from)
- struct shf *shf;
- off_t where;
- int from;
-{
- if (shf->fd < 0) {
- errno = EINVAL;
- return EOF;
- }
-
- if (shf->flags & SHF_ERROR) {
- errno = shf->errno_;
- return EOF;
- }
-
- if ((shf->flags & SHF_WRITING) && shf_emptybuf(shf, EB_READSW) == EOF)
- return EOF;
-
- if (shf->flags & SHF_READING) {
- if (from == SEEK_CUR &&
- (where < 0 ?
- -where >= shf->rbsize - shf->rnleft :
- where < shf->rnleft)) {
- shf->rnleft -= where;
- shf->rp += where;
- return 0;
- }
- shf->rnleft = 0;
- shf->rp = shf->buf;
- }
-
- shf->flags &= ~(SHF_EOF | SHF_READING | SHF_WRITING);
-
- if (lseek(shf->fd, where, from) < 0) {
- shf->errno_ = errno;
- shf->flags |= SHF_ERROR;
- return EOF;
- }
-
- return 0;
-}
-
-
-/* Read a buffer from shf. Returns the number of bytes read into buf,
- * if no bytes were read, returns 0 if end of file was seen, EOF if
- * a read error occurred.
- */
-int
-shf_read(buf, bsize, shf)
- char *buf;
- int bsize;
- struct shf *shf;
-{
- int orig_bsize = bsize;
- int ncopy;
-
- if (!(shf->flags & SHF_RD))
- internal_errorf(1, "shf_read: flags %x", shf->flags);
-
- if (bsize <= 0)
- internal_errorf(1, "shf_read: bsize %d", bsize);
-
- while (bsize > 0) {
- if (shf->rnleft == 0
- && (shf_fillbuf(shf) == EOF || shf->rnleft == 0))
- break;
- ncopy = shf->rnleft;
- if (ncopy > bsize)
- ncopy = bsize;
- memcpy(buf, shf->rp, ncopy);
- buf += ncopy;
- bsize -= ncopy;
- shf->rp += ncopy;
- shf->rnleft -= ncopy;
- }
- /* Note: fread(3S) returns 0 for errors - this doesn't */
- return orig_bsize == bsize ? (shf_error(shf) ? EOF : 0)
- : orig_bsize - bsize;
-}
-
-/* Read up to a newline or EOF. The newline is put in buf; buf is always
- * null terminated. Returns NULL on read error or if nothing was read before
- * end of file, returns a pointer to the null byte in buf otherwise.
- */
-char *
-shf_getse(buf, bsize, shf)
- char *buf;
- int bsize;
- struct shf *shf;
-{
- unsigned char *end;
- int ncopy;
- char *orig_buf = buf;
-
- if (!(shf->flags & SHF_RD))
- internal_errorf(1, "shf_getse: flags %x", shf->flags);
-
- if (bsize <= 0)
- return (char *) 0;
-
- --bsize; /* save room for null */
- do {
- if (shf->rnleft == 0) {
- if (shf_fillbuf(shf) == EOF)
- return NULL;
- if (shf->rnleft == 0) {
- *buf = '\0';
- return buf == orig_buf ? NULL : buf;
- }
- }
- end = (unsigned char *) memchr((char *) shf->rp, '\n',
- shf->rnleft);
- ncopy = end ? end - shf->rp + 1 : shf->rnleft;
- if (ncopy > bsize)
- ncopy = bsize;
- memcpy(buf, (char *) shf->rp, ncopy);
- shf->rp += ncopy;
- shf->rnleft -= ncopy;
- buf += ncopy;
- bsize -= ncopy;
- } while (!end && bsize);
- *buf = '\0';
- return buf;
-}
-
-/* Returns the char read. Returns EOF for error and end of file. */
-int
-shf_getchar(shf)
- struct shf *shf;
-{
- if (!(shf->flags & SHF_RD))
- internal_errorf(1, "shf_getchar: flags %x", shf->flags);
-
- if (shf->rnleft == 0 && (shf_fillbuf(shf) == EOF || shf->rnleft == 0))
- return EOF;
- --shf->rnleft;
- return *shf->rp++;
-}
-
-/* Put a character back in the input stream. Returns the character if
- * successful, EOF if there is no room.
- */
-int
-shf_ungetc(c, shf)
- int c;
- struct shf *shf;
-{
- if (!(shf->flags & SHF_RD))
- internal_errorf(1, "shf_ungetc: flags %x", shf->flags);
-
- if ((shf->flags & SHF_ERROR) || c == EOF
- || (shf->rp == shf->buf && shf->rnleft))
- return EOF;
-
- if ((shf->flags & SHF_WRITING) && shf_emptybuf(shf, EB_READSW) == EOF)
- return EOF;
-
- if (shf->rp == shf->buf)
- shf->rp = shf->buf + shf->rbsize;
- if (shf->flags & SHF_STRING) {
- /* Can unget what was read, but not something different - we
- * don't want to modify a string.
- */
- if (shf->rp[-1] != c)
- return EOF;
- shf->flags &= ~SHF_EOF;
- shf->rp--;
- shf->rnleft++;
- return c;
- }
- shf->flags &= ~SHF_EOF;
- *--(shf->rp) = c;
- shf->rnleft++;
- return c;
-}
-
-/* Write a character. Returns the character if successful, EOF if
- * the char could not be written.
- */
-int
-shf_putchar(c, shf)
- int c;
- struct shf *shf;
-{
- if (!(shf->flags & SHF_WR))
- internal_errorf(1, "shf_putchar: flags %x", shf->flags);
-
- if (c == EOF)
- return EOF;
-
- if (shf->flags & SHF_UNBUF) {
- char cc = c;
- int n;
-
- if (shf->fd < 0)
- internal_errorf(1, "shf_putchar: no fd");
- if (shf->flags & SHF_ERROR) {
- errno = shf->errno_;
- return EOF;
- }
- while ((n = write(shf->fd, &cc, 1)) != 1)
- if (n < 0) {
- if (errno == EINTR
- && !(shf->flags & SHF_INTERRUPT))
- continue;
- shf->flags |= SHF_ERROR;
- shf->errno_ = errno;
- return EOF;
- }
- } else {
- /* Flush deals with strings and sticky errors */
- if (shf->wnleft == 0 && shf_emptybuf(shf, EB_GROW) == EOF)
- return EOF;
- shf->wnleft--;
- *shf->wp++ = c;
- }
-
- return c;
-}
-
-/* Write a string. Returns the length of the string if successful, EOF if
- * the string could not be written.
- */
-int
-shf_puts(s, shf)
- const char *s;
- struct shf *shf;
-{
- if (!s)
- return EOF;
-
- return shf_write(s, strlen(s), shf);
-}
-
-/* Write a buffer. Returns nbytes if successful, EOF if there is an error. */
-int
-shf_write(buf, nbytes, shf)
- const char *buf;
- int nbytes;
- struct shf *shf;
-{
- int orig_nbytes = nbytes;
- int n;
- int ncopy;
-
- if (!(shf->flags & SHF_WR))
- internal_errorf(1, "shf_write: flags %x", shf->flags);
-
- if (nbytes < 0)
- internal_errorf(1, "shf_write: nbytes %d", nbytes);
-
- if ((ncopy = shf->wnleft)) {
- if (ncopy > nbytes)
- ncopy = nbytes;
- memcpy(shf->wp, buf, ncopy);
- nbytes -= ncopy;
- buf += ncopy;
- shf->wp += ncopy;
- shf->wnleft -= ncopy;
- }
- if (nbytes > 0) {
- /* Flush deals with strings and sticky errors */
- if (shf_emptybuf(shf, EB_GROW) == EOF)
- return EOF;
- if (nbytes > shf->wbsize) {
- ncopy = nbytes;
- if (shf->wbsize)
- ncopy -= nbytes % shf->wbsize;
- nbytes -= ncopy;
- while (ncopy > 0) {
- n = write(shf->fd, buf, ncopy);
- if (n < 0) {
- if (errno == EINTR
- && !(shf->flags & SHF_INTERRUPT))
- continue;
- shf->flags |= SHF_ERROR;
- shf->errno_ = errno;
- shf->wnleft = 0;
- /* Note: fwrite(3S) returns 0 for
- * errors - this doesn't */
- return EOF;
- }
- buf += n;
- ncopy -= n;
- }
- }
- if (nbytes > 0) {
- memcpy(shf->wp, buf, nbytes);
- shf->wp += nbytes;
- shf->wnleft -= nbytes;
- }
- }
-
- return orig_nbytes;
-}
-
-int
-#ifdef HAVE_PROTOTYPES
-shf_fprintf(struct shf *shf, const char *fmt, ...)
-#else
-shf_fprintf(shf, fmt, va_alist)
- struct shf *shf;
- const char *fmt;
- va_dcl
-#endif
-{
- va_list args;
- int n;
-
- SH_VA_START(args, fmt);
- n = shf_vfprintf(shf, fmt, args);
- va_end(args);
-
- return n;
-}
-
-int
-#ifdef HAVE_PROTOTYPES
-shf_snprintf(char *buf, int bsize, const char *fmt, ...)
-#else
-shf_snprintf(buf, bsize, fmt, va_alist)
- char *buf;
- int bsize;
- const char *fmt;
- va_dcl
-#endif
-{
- struct shf shf;
- va_list args;
- int n;
-
- if (!buf || bsize <= 0)
- internal_errorf(1, "shf_snprintf: buf %lx, bsize %d",
- (long) buf, bsize);
-
- shf_sopen(buf, bsize, SHF_WR, &shf);
- SH_VA_START(args, fmt);
- n = shf_vfprintf(&shf, fmt, args);
- va_end(args);
- shf_sclose(&shf); /* null terminates */
- return n;
-}
-
-char *
-#ifdef HAVE_PROTOTYPES
-shf_smprintf(const char *fmt, ...)
-#else
-shf_smprintf(fmt, va_alist)
- char *fmt;
- va_dcl
-#endif
-{
- struct shf shf;
- va_list args;
-
- shf_sopen((char *) 0, 0, SHF_WR|SHF_DYNAMIC, &shf);
- SH_VA_START(args, fmt);
- shf_vfprintf(&shf, fmt, args);
- va_end(args);
- return shf_sclose(&shf); /* null terminates */
-}
-
-#undef FP /* if you want floating point stuff */
-
-#define BUF_SIZE 128
-#define FPBUF_SIZE (DMAXEXP+16)/* this must be >
- * MAX(DMAXEXP, log10(pow(2, DSIGNIF)))
- * + ceil(log10(DMAXEXP)) + 8 (I think).
- * Since this is hard to express as a
- * constant, just use a large buffer.
- */
-
-/*
- * What kinda of machine we on? Hopefully the C compiler will optimize
- * this out...
- *
- * For shorts, we want sign extend for %d but not for %[oxu] - on 16 bit
- * machines it don't matter. Assmumes C compiler has converted shorts to
- * ints before pushing them.
- */
-#define POP_INT(f, s, a) (((f) & FL_LONG) ? \
- va_arg((a), unsigned long) \
- : \
- (sizeof(int) < sizeof(long) ? \
- ((s) ? \
- (long) va_arg((a), int) \
- : \
- va_arg((a), unsigned)) \
- : \
- va_arg((a), unsigned)))
-
-#define ABIGNUM 32000 /* big numer that will fit in a short */
-#define LOG2_10 3.321928094887362347870319429 /* log base 2 of 10 */
-
-#define FL_HASH 0x001 /* `#' seen */
-#define FL_PLUS 0x002 /* `+' seen */
-#define FL_RIGHT 0x004 /* `-' seen */
-#define FL_BLANK 0x008 /* ` ' seen */
-#define FL_SHORT 0x010 /* `h' seen */
-#define FL_LONG 0x020 /* `l' seen */
-#define FL_ZERO 0x040 /* `0' seen */
-#define FL_DOT 0x080 /* '.' seen */
-#define FL_UPPER 0x100 /* format character was uppercase */
-#define FL_NUMBER 0x200 /* a number was formated %[douxefg] */
-
-
-#ifdef FP
-#include <math.h>
-
-static double
-my_ceil(d)
- double d;
-{
- double i;
-
- return d - modf(d, &i) + (d < 0 ? -1 : 1);
-}
-#endif /* FP */
-
-int
-shf_vfprintf(shf, fmt, args)
- struct shf *shf;
- const char *fmt;
- va_list args;
-{
- char c, *s;
- int UNINITIALIZED(tmp);
- int field, precision;
- int len;
- int flags;
- unsigned long lnum;
- /* %#o produces the longest output */
- char numbuf[(BITS(long) + 2) / 3 + 1];
- /* this stuff for dealing with the buffer */
- int nwritten = 0;
-#ifdef FP
- /* should be in <math.h>
- * extern double frexp();
- */
- extern char *ecvt();
-
- double fpnum;
- int expo, decpt;
- char style;
- char fpbuf[FPBUF_SIZE];
-#endif /* FP */
-
- if (!fmt)
- return 0;
-
- while ((c = *fmt++)) {
- if (c != '%') {
- shf_putc(c, shf);
- nwritten++;
- continue;
- }
- /*
- * This will accept flags/fields in any order - not
- * just the order specified in printf(3), but this is
- * the way _doprnt() seems to work (on bsd and sysV).
- * The only resriction is that the format character must
- * come last :-).
- */
- flags = field = precision = 0;
- for ( ; (c = *fmt++) ; ) {
- switch (c) {
- case '#':
- flags |= FL_HASH;
- continue;
-
- case '+':
- flags |= FL_PLUS;
- continue;
-
- case '-':
- flags |= FL_RIGHT;
- continue;
-
- case ' ':
- flags |= FL_BLANK;
- continue;
-
- case '0':
- if (!(flags & FL_DOT))
- flags |= FL_ZERO;
- continue;
-
- case '.':
- flags |= FL_DOT;
- precision = 0;
- continue;
-
- case '*':
- tmp = va_arg(args, int);
- if (flags & FL_DOT)
- precision = tmp;
- else if ((field = tmp) < 0) {
- field = -field;
- flags |= FL_RIGHT;
- }
- continue;
-
- case 'l':
- flags |= FL_LONG;
- continue;
-
- case 'h':
- flags |= FL_SHORT;
- continue;
- }
- if (digit(c)) {
- tmp = c - '0';
- while (c = *fmt++, digit(c))
- tmp = tmp * 10 + c - '0';
- --fmt;
- if (tmp < 0) /* overflow? */
- tmp = 0;
- if (flags & FL_DOT)
- precision = tmp;
- else
- field = tmp;
- continue;
- }
- break;
- }
-
- if (precision < 0)
- precision = 0;
-
- if (!c) /* nasty format */
- break;
-
- if (c >= 'A' && c <= 'Z') {
- flags |= FL_UPPER;
- c = c - 'A' + 'a';
- }
-
- switch (c) {
- case 'p': /* pointer */
- flags &= ~(FL_LONG | FL_SHORT);
- if (sizeof(char *) > sizeof(int))
- flags |= FL_LONG; /* hope it fits.. */
- /* aaahhh... */
- case 'd':
- case 'i':
- case 'o':
- case 'u':
- case 'x':
- flags |= FL_NUMBER;
- s = &numbuf[sizeof(numbuf)];
- lnum = POP_INT(flags, c == 'd', args);
- switch (c) {
- case 'd':
- case 'i':
- if (0 > (long) lnum)
- lnum = - (long) lnum, tmp = 1;
- else
- tmp = 0;
- /* aaahhhh..... */
-
- case 'u':
- do {
- *--s = lnum % 10 + '0';
- lnum /= 10;
- } while (lnum);
-
- if (c != 'u') {
- if (tmp)
- *--s = '-';
- else if (flags & FL_PLUS)
- *--s = '+';
- else if (flags & FL_BLANK)
- *--s = ' ';
- }
- break;
-
- case 'o':
- do {
- *--s = (lnum & 0x7) + '0';
- lnum >>= 3;
- } while (lnum);
-
- if ((flags & FL_HASH) && *s != '0')
- *--s = '0';
- break;
-
- case 'p':
- case 'x':
- {
- const char *digits = (flags & FL_UPPER) ?
- "0123456789ABCDEF"
- : "0123456789abcdef";
- do {
- *--s = digits[lnum & 0xf];
- lnum >>= 4;
- } while (lnum);
-
- if (flags & FL_HASH) {
- *--s = (flags & FL_UPPER) ? 'X' : 'x';
- *--s = '0';
- }
- }
- }
- len = &numbuf[sizeof(numbuf)] - s;
- if (flags & FL_DOT) {
- if (precision > len) {
- field = precision;
- flags |= FL_ZERO;
- } else
- precision = len; /* no loss */
- }
- break;
-
-#ifdef FP
- case 'e':
- case 'g':
- case 'f':
- {
- char *p;
-
- /*
- * This could proabably be done better,
- * but it seems to work. Note that gcvt()
- * is not used, as you cannot tell it to
- * not strip the zeros.
- */
- flags |= FL_NUMBER;
- if (!(flags & FL_DOT))
- precision = 6; /* default */
- /*
- * Assumes doubles are pushed on
- * the stack. If this is not so, then
- * FL_LONG/FL_SHORT should be checked.
- */
- fpnum = va_arg(args, double);
- s = fpbuf;
- style = c;
- /*
- * This is the same as
- * expo = ceil(log10(fpnum))
- * but doesn't need -lm. This is an
- * aproximation as expo is rounded up.
- */
- (void) frexp(fpnum, &expo);
- expo = my_ceil(expo / LOG2_10);
-
- if (expo < 0)
- expo = 0;
-
- p = ecvt(fpnum, precision + 1 + expo,
- &decpt, &tmp);
- if (c == 'g') {
- if (decpt < -4 || decpt > precision)
- style = 'e';
- else
- style = 'f';
- if (decpt > 0 && (precision -= decpt) < 0)
- precision = 0;
- }
- if (tmp)
- *--s = '-';
- else if (flags & FL_PLUS)
- *--s = '+';
- else if (flags & FL_BLANK)
- *--s = ' ';
-
- if (style == 'e')
- *s++ = *p++;
- else {
- if (decpt > 0) {
- /* Overflow check - should
- * never have this problem.
- */
- if (decpt >
- &fpbuf[sizeof(fpbuf)]
- - s - 8)
- decpt =
- &fpbuf[sizeof(fpbuf)]
- - s - 8;
- (void) memcpy(s, p, decpt);
- s += decpt;
- p += decpt;
- } else
- *s++ = '0';
- }
-
- /* print the fraction? */
- if (precision > 0) {
- *s++ = '.';
- /* Overflow check - should
- * never have this problem.
- */
- if (precision > &fpbuf[sizeof(fpbuf)]
- - s - 7)
- precision =
- &fpbuf[sizeof(fpbuf)]
- - s - 7;
- for (tmp = decpt; tmp++ < 0 &&
- precision > 0 ; precision--)
- *s++ = '0';
- tmp = strlen(p);
- if (precision > tmp)
- precision = tmp;
- /* Overflow check - should
- * never have this problem.
- */
- if (precision > &fpbuf[sizeof(fpbuf)]
- - s - 7)
- precision =
- &fpbuf[sizeof(fpbuf)]
- - s - 7;
- (void) memcpy(s, p, precision);
- s += precision;
- /*
- * `g' format strips trailing
- * zeros after the decimal.
- */
- if (c == 'g' && !(flags & FL_HASH)) {
- while (*--s == '0')
- ;
- if (*s != '.')
- s++;
- }
- } else if (flags & FL_HASH)
- *s++ = '.';
-
- if (style == 'e') {
- *s++ = (flags & FL_UPPER) ? 'E' : 'e';
- if (--decpt >= 0)
- *s++ = '+';
- else {
- *s++ = '-';
- decpt = -decpt;
- }
- p = &numbuf[sizeof(numbuf)];
- for (tmp = 0; tmp < 2 || decpt ; tmp++) {
- *--p = '0' + decpt % 10;
- decpt /= 10;
- }
- tmp = &numbuf[sizeof(numbuf)] - p;
- (void) memcpy(s, p, tmp);
- s += tmp;
- }
-
- len = s - fpbuf;
- s = fpbuf;
- precision = len;
- break;
- }
-#endif /* FP */
-
- case 's':
- if (!(s = va_arg(args, char *)))
- s = "(null %s)";
- len = strlen(s);
- break;
-
- case 'c':
- flags &= ~FL_DOT;
- numbuf[0] = va_arg(args, int);
- s = numbuf;
- len = 1;
- break;
-
- case '%':
- default:
- numbuf[0] = c;
- s = numbuf;
- len = 1;
- break;
- }
-
- /*
- * At this point s should point to a string that is
- * to be formatted, and len should be the length of the
- * string.
- */
- if (!(flags & FL_DOT) || len < precision)
- precision = len;
- if (field > precision) {
- field -= precision;
- if (!(flags & FL_RIGHT)) {
- field = -field;
- /* skip past sign or 0x when padding with 0 */
- if ((flags & FL_ZERO) && (flags & FL_NUMBER)) {
- if (*s == '+' || *s == '-' || *s ==' ')
- {
- shf_putc(*s, shf);
- s++;
- precision--;
- nwritten++;
- } else if (*s == '0') {
- shf_putc(*s, shf);
- s++;
- nwritten++;
- if (--precision > 0 &&
- (*s | 0x20) == 'x')
- {
- shf_putc(*s, shf);
- s++;
- precision--;
- nwritten++;
- }
- }
- c = '0';
- } else
- c = flags & FL_ZERO ? '0' : ' ';
- if (field < 0) {
- nwritten += -field;
- for ( ; field < 0 ; field++)
- shf_putc(c, shf);
- }
- } else
- c = ' ';
- } else
- field = 0;
-
- if (precision > 0) {
- nwritten += precision;
- for ( ; precision-- > 0 ; s++)
- shf_putc(*s, shf);
- }
- if (field > 0) {
- nwritten += field;
- for ( ; field > 0 ; --field)
- shf_putc(c, shf);
- }
- }
-
- return shf_error(shf) ? EOF : nwritten;
-}
diff --git a/bin/pdksh/shf.h b/bin/pdksh/shf.h
deleted file mode 100644
index 2069d3248b8..00000000000
--- a/bin/pdksh/shf.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/* $OpenBSD: shf.h,v 1.1 1996/08/14 06:19:11 downsj Exp $ */
-
-/*
- * Shell file I/O routines
- */
-
-#define SHF_BSIZE 512
-
-#define shf_fileno(shf) ((shf)->fd)
-#define shf_setfileno(shf,nfd) ((shf)->fd = (nfd))
-#define shf_getc(shf) ((shf)->rnleft > 0 ? (shf)->rnleft--, *(shf)->rp++ : \
- shf_getchar(shf))
-#define shf_putc(c, shf) ((shf)->wnleft == 0 ? shf_putchar((c), (shf)) \
- : ((shf)->wnleft--, *(shf)->wp++ = (c)))
-#define shf_eof(shf) ((shf)->flags & SHF_EOF)
-#define shf_error(shf) ((shf)->flags & SHF_ERROR)
-#define shf_errno(shf) ((shf)->errno_)
-#define shf_clearerr(shf) ((shf)->flags &= ~(SHF_EOF | SHF_ERROR))
-
-/* Flags passed to shf_*open() */
-#define SHF_RD 0x0001
-#define SHF_WR 0x0002
-#define SHF_RDWR (SHF_RD|SHF_WR)
-#define SHF_ACCMODE 0x0003 /* mask */
-#define SHF_GETFL 0x0004 /* use fcntl() to figure RD/WR flags */
-#define SHF_UNBUF 0x0008 /* unbuffered I/O */
-#define SHF_CLEXEC 0x0010 /* set close on exec flag */
-#define SHF_MAPHI 0x0020 /* make fd > FDBASE (and close orig)
- * (shf_open() only) */
-#define SHF_DYNAMIC 0x0040 /* string: increase buffer as needed */
-#define SHF_INTERRUPT 0x0080 /* EINTR in read/write causes error */
-/* Flags used internally */
-#define SHF_STRING 0x0100 /* a string, not a file */
-#define SHF_ALLOCS 0x0200 /* shf and shf->buf were alloc()ed */
-#define SHF_ALLOCB 0x0400 /* shf->buf was alloc()ed */
-#define SHF_ERROR 0x0800 /* read()/write() error */
-#define SHF_EOF 0x1000 /* read eof (sticky) */
-#define SHF_READING 0x2000 /* currently reading: rnleft,rp valid */
-#define SHF_WRITING 0x4000 /* currently writing: wnleft,wp valid */
-
-
-struct shf {
- int flags; /* see SHF_* */
- unsigned char *rp; /* read: current position in buffer */
- int rbsize; /* size of buffer (1 if SHF_UNBUF) */
- int rnleft; /* read: how much data left in buffer */
- unsigned char *wp; /* write: current position in buffer */
- int wbsize; /* size of buffer (0 if SHF_UNBUF) */
- int wnleft; /* write: how much space left in buffer */
- unsigned char *buf; /* buffer */
- int fd; /* file descriptor */
- int errno_; /* saved value of errno after error */
- int bsize; /* actual size of buf */
- Area *areap; /* area shf/buf were allocated in */
-};
-
-extern struct shf shf_iob[];
-
-struct shf *shf_open ARGS((const char *name, int oflags, int mode,
- int sflags));
-struct shf *shf_fdopen ARGS((int fd, int sflags, struct shf *shf));
-struct shf *shf_reopen ARGS((int fd, int sflags, struct shf *shf));
-struct shf *shf_sopen ARGS((char *buf, int bsize, int sflags,
- struct shf *shf));
-int shf_close ARGS((struct shf *shf));
-int shf_fdclose ARGS((struct shf *shf));
-char *shf_sclose ARGS((struct shf *shf));
-int shf_finish ARGS((struct shf *shf));
-int shf_flush ARGS((struct shf *shf));
-int shf_seek ARGS((struct shf *shf, off_t where, int from));
-int shf_read ARGS((char *buf, int bsize, struct shf *shf));
-char *shf_getse ARGS((char *buf, int bsize, struct shf *shf));
-int shf_getchar ARGS((struct shf *shf));
-int shf_ungetc ARGS((int c, struct shf *shf));
-int shf_putchar ARGS((int c, struct shf *shf));
-int shf_puts ARGS((const char *s, struct shf *shf));
-int shf_write ARGS((const char *buf, int nbytes, struct shf *shf));
-int shf_fprintf ARGS((struct shf *shf, const char *fmt, ...));
-int shf_snprintf ARGS((char *buf, int bsize, const char *fmt, ...));
-char *shf_smprintf ARGS((const char *fmt, ...));
-int shf_vfprintf ARGS((struct shf *, const char *fmt, va_list args));
diff --git a/bin/pdksh/siglist.in b/bin/pdksh/siglist.in
deleted file mode 100644
index de6f1dd849f..00000000000
--- a/bin/pdksh/siglist.in
+++ /dev/null
@@ -1,56 +0,0 @@
-# $OpenBSD: siglist.in,v 1.1 1996/08/14 06:19:11 downsj Exp $
-#
-# List of signals used to initialize ksh's signal table (see trap.c
-# and siglist.sh).
-#
-# Note that if a system has multiple defines for the same signal
-# (eg, SIGABRT vs SIGIOT, SIGCHLD vs SIGCLD), only the first one
-# will be seen, so the order in this list is important.
-#
- HUP Hangup
- INT Interrupt
- QUIT Quit
- ILL Illegal instruction
- TRAP Trace trap
-# before IOT (ABRT is posix and ABRT is sometimes the same as IOT)
- ABRT Abort
- IOT IOT instruction
- EMT EMT trap
- FPE Floating point exception
- KILL Killed
-# before BUS (linux doesn't really have a BUS, but defines it to UNUSED)
- UNUSED Unused
- BUS Bus error
- SEGV Memory fault
- SYS Bad system call
- PIPE Broken pipe
- ALRM Alarm clock
- TERM Terminated
- STKFLT Stack fault
- IO I/O possible
- XCPU CPU time limit exceeded
- XFSZ File size limit exceeded
- VTALRM Virtual timer expired
- PROF Profiling timer expired
- WINCH Window size change
- LOST File lock lost
- USR1 User defined signal 1
- USR2 User defined signal 2
- PWR Power-fail/Restart
- POLL Pollable event occurred
- STOP Stopped (signal)
- TSTP Stopped
- CONT Continued
-# before CLD (CHLD is posix and CHLD is sometimes the same as CLD)
- CHLD Child exited
- CLD Child exited
- TTIN Stopped (tty input)
- TTOU Stopped (tty output)
- INFO Information request
- URG Urgent I/O condition
-# Solaris (svr4?) signals
- WAITING No runnable LWPs
- LWP Inter-LWP signal
- FREEZE Checkpoint freeze
- THAW Checkpoint thaw
- CANCEL Thread cancellation
diff --git a/bin/pdksh/siglist.sh b/bin/pdksh/siglist.sh
deleted file mode 100644
index 123b190140c..00000000000
--- a/bin/pdksh/siglist.sh
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/bin/sh
-# $OpenBSD: siglist.sh,v 1.4 1997/06/19 13:58:47 kstailey Exp $
-
-#
-# Script to generate a sorted, complete list of signals, suitable
-# for inclusion in trap.c as array initializer.
-#
-
-set -e
-
-in=tmpi$$.c
-out=tmpo$$.c
-ecode=1
-trapsigs='0 1 2 13 15'
-trap 'rm -f $in $out; trap 0; exit $ecode' $trapsigs
-
-CPP="${1-cc -E}"
-
-# The trap here to make up for a bug in bash (1.14.3(1)) that calls the trap
-(trap $trapsigs;
- echo '#include "sh.h"';
- echo ' { QwErTy SIGNALS , "DUMMY" , "hook for number of signals" },';
- sed -e '/^[ ]*#/d' -e 's/^[ ]*\([^ ][^ ]*\)[ ][ ]*\(.*[^ ]\)[ ]*$/#ifdef SIG\1\
- { QwErTy SIG\1 , "\1", "\2" },\
-#endif/') > $in
-$CPP $in > $out
-sed -n 's/{ QwErTy/{/p' < $out | awk '{print NR, $0}' | sort +2n +0n |
- sed 's/^[0-9]* //' |
- awk 'BEGIN { last=0; nsigs=0; }
- {
- if ($2 ~ /^[0-9][0-9]*$/ && $3 == ",") {
- n = $2;
- if (n > 0 && n != last) {
- while (++last < n) {
- printf "\t{ %d , (char *) 0, `Signal %d` } ,\n", last, last;
- }
- print;
- }
- }
- }' |
- tr '`' '"' | grep -v '"DUMMY"'
-ecode=0
diff --git a/bin/pdksh/syn.c b/bin/pdksh/syn.c
deleted file mode 100644
index 4b37baa819d..00000000000
--- a/bin/pdksh/syn.c
+++ /dev/null
@@ -1,948 +0,0 @@
-/* $OpenBSD: syn.c,v 1.8 1997/09/01 18:30:12 deraadt Exp $ */
-
-/*
- * shell parser (C version)
- */
-
-#include "sh.h"
-#include "c_test.h"
-
-struct multiline_state {
- int on; /* set in multiline commands (\n becomes ;) */
- int start_token; /* token multiline is for (eg, FOR, {, etc.) */
- int start_line; /* line multiline command started on */
-};
-
-static void yyparse ARGS((void));
-static struct op *pipeline ARGS((int cf));
-static struct op *andor ARGS((void));
-static struct op *c_list ARGS((void));
-static struct ioword *synio ARGS((int cf));
-static void musthave ARGS((int c, int cf));
-static struct op *nested ARGS((int type, int smark, int emark));
-static struct op *get_command ARGS((int cf));
-static struct op *dogroup ARGS((void));
-static struct op *thenpart ARGS((void));
-static struct op *elsepart ARGS((void));
-static struct op *caselist ARGS((void));
-static struct op *casepart ARGS((int endtok));
-static struct op *function_body ARGS((char *name, int ksh_func));
-static char ** wordlist ARGS((void));
-static struct op *block ARGS((int type, struct op *t1, struct op *t2,
- char **wp));
-static struct op *newtp ARGS((int type));
-static void syntaxerr ARGS((const char *what))
- GCC_FUNC_ATTR(noreturn);
-static void multiline_push ARGS((struct multiline_state *save, int tok));
-static void multiline_pop ARGS((struct multiline_state *saved));
-static int assign_command ARGS((char *s));
-static int inalias ARGS((struct source *s));
-#ifdef KSH
-static int dbtestp_isa ARGS((Test_env *te, Test_meta meta));
-static const char *dbtestp_getopnd ARGS((Test_env *te, Test_op op,
- int do_eval));
-static int dbtestp_eval ARGS((Test_env *te, Test_op op, const char *opnd1,
- const char *opnd2, int do_eval));
-static void dbtestp_error ARGS((Test_env *te, int offset, const char *msg));
-#endif /* KSH */
-
-static struct op *outtree; /* yyparse output */
-
-static struct multiline_state multiline; /* \n changed to ; */
-
-static int reject; /* token(cf) gets symbol again */
-static int symbol; /* yylex value */
-
-#define REJECT (reject = 1)
-#define ACCEPT (reject = 0)
-#define token(cf) \
- ((reject) ? (ACCEPT, symbol) : (symbol = yylex(cf)))
-#define tpeek(cf) \
- ((reject) ? (symbol) : (REJECT, symbol = yylex(cf)))
-
-static void
-yyparse()
-{
- int c;
-
- ACCEPT;
- yynerrs = 0;
-
- outtree = c_list();
- c = tpeek(0);
- if (c == 0 && !outtree)
- outtree = newtp(TEOF);
- else if (c != '\n' && c != 0)
- syntaxerr((char *) 0);
-}
-
-static struct op *
-pipeline(cf)
- int cf;
-{
- register struct op *t, *p, *tl = NULL;
-
- t = get_command(cf);
- if (t != NULL) {
- while (token(0) == '|') {
- if ((p = get_command(CONTIN)) == NULL)
- syntaxerr((char *) 0);
- if (tl == NULL)
- t = tl = block(TPIPE, t, p, NOWORDS);
- else
- tl = tl->right = block(TPIPE, tl->right, p, NOWORDS);
- }
- REJECT;
- }
- return (t);
-}
-
-static struct op *
-andor()
-{
- register struct op *t, *p;
- register int c;
-
- t = pipeline(0);
- if (t != NULL) {
- while ((c = token(0)) == LOGAND || c == LOGOR) {
- if ((p = pipeline(CONTIN)) == NULL)
- syntaxerr((char *) 0);
- t = block(c == LOGAND? TAND: TOR, t, p, NOWORDS);
- }
- REJECT;
- }
- return (t);
-}
-
-static struct op *
-c_list()
-{
- register struct op *t, *p, *tl = NULL;
- register int c;
-
- t = andor();
- if (t != NULL) {
- /* Token has always been read/rejected at this point, so
- * we don't worray about what flags to pass token()
- */
- while ((c = token(0)) == ';' || c == '&' || c == COPROC ||
- (c == '\n' && (multiline.on || inalias(source))))
- {
- if (c == '&' || c == COPROC) {
- int type = c == '&' ? TASYNC : TCOPROC;
- if (tl)
- tl->right = block(type, tl->right,
- NOBLOCK, NOWORDS);
- else
- t = block(type, t, NOBLOCK, NOWORDS);
- }
- if ((p = andor()) == NULL)
- return (t);
- if (tl == NULL)
- t = tl = block(TLIST, t, p, NOWORDS);
- else
- tl = tl->right = block(TLIST, tl->right, p, NOWORDS);
- }
- REJECT;
- }
- return (t);
-}
-
-static struct ioword *
-synio(cf)
- int cf;
-{
- register struct ioword *iop;
- int ishere;
-
- if (tpeek(cf) != REDIR)
- return NULL;
- ACCEPT;
- iop = yylval.iop;
- ishere = (iop->flag&IOTYPE) == IOHERE;
- musthave(LWORD, ishere ? HEREDELIM : 0);
- if (ishere) {
- iop->delim = yylval.cp;
- if (*ident != 0) /* unquoted */
- iop->flag |= IOEVAL;
- if (herep >= &heres[HERES])
- yyerror("too many <<'s\n");
- *herep++ = iop;
- } else
- iop->name = yylval.cp;
- return iop;
-}
-
-static void
-musthave(c, cf)
- int c, cf;
-{
- if ((token(cf)) != c)
- syntaxerr((char *) 0);
-}
-
-static struct op *
-nested(type, smark, emark)
- int type, smark, emark;
-{
- register struct op *t;
- struct multiline_state old_multiline;
-
- multiline_push(&old_multiline, smark);
- t = c_list();
- musthave(emark, KEYWORD|ALIAS);
- multiline_pop(&old_multiline);
- return (block(type, t, NOBLOCK, NOWORDS));
-}
-
-static struct op *
-get_command(cf)
- int cf;
-{
- register struct op *t;
- register int c, iopn = 0, syniocf;
- struct ioword *iop, **iops;
- XPtrV args, vars;
- struct multiline_state old_multiline;
-
- iops = (struct ioword **) alloc(sizeofN(struct ioword *, NUFILE+1),
- ATEMP);
- XPinit(args, 16);
- XPinit(vars, 16);
-
- /* Don't want to pass CONTIN if reading interactively as just hitting
- * return would print PS2 instead of PS1.
- */
- if (multiline.on || inalias(source))
- cf = CONTIN;
- syniocf = KEYWORD|ALIAS;
- switch (c = token(cf|KEYWORD|ALIAS|VARASN)) {
- default:
- REJECT;
- afree((void*) iops, ATEMP);
- XPfree(args);
- XPfree(vars);
- return NULL; /* empty line */
-
- case LWORD:
- case REDIR:
- REJECT;
- syniocf &= ~(KEYWORD|ALIAS);
- t = newtp(TCOM);
- while (1) {
- cf = (t->u.evalflags ? ARRAYVAR : 0)
- | (XPsize(args) == 0 ? ALIAS|VARASN : CMDWORD);
- switch (tpeek(cf)) {
- case REDIR:
- if (iopn >= NUFILE)
- yyerror("too many redirections\n");
- iops[iopn++] = synio(cf);
- break;
-
- case LWORD:
- ACCEPT;
- /* the iopn == 0 and XPsize(vars) == 0 are
- * dubious but at&t ksh acts this way
- */
- if (iopn == 0 && XPsize(vars) == 0
- && XPsize(args) == 0
- && assign_command(ident))
- t->u.evalflags = DOVACHECK;
- if ((XPsize(args) == 0 || Flag(FKEYWORD))
- && is_wdvarassign(yylval.cp))
- XPput(vars, yylval.cp);
- else
- XPput(args, yylval.cp);
- break;
-
- case '(':
- /* Check for "> foo (echo hi)", which at&t ksh
- * allows (not POSIX, but not disallowed)
- */
- afree(t, ATEMP);
- if (XPsize(args) == 0 && XPsize(vars) == 0) {
- ACCEPT;
- goto Subshell;
- }
- /* Must be a function */
- if (iopn != 0 || XPsize(args) != 1
- || XPsize(vars) != 0)
- syntaxerr((char *) 0);
- ACCEPT;
- /*(*/
- musthave(')', 0);
- t = function_body(XPptrv(args)[0], FALSE);
- goto Leave;
-
- default:
- goto Leave;
- }
- }
- Leave:
- break;
-
- Subshell:
- case '(':
- t = nested(TPAREN, '(', ')');
- break;
-
- case '{': /*}*/
- t = nested(TBRACE, '{', '}');
- break;
-
-#ifdef KSH
- case MDPAREN:
- {
- static const char let_cmd[] = { CHAR, 'l', CHAR, 'e',
- CHAR, 't', EOS };
- syniocf &= ~(KEYWORD|ALIAS);
- t = newtp(TCOM);
- ACCEPT;
- XPput(args, wdcopy(let_cmd, ATEMP));
- musthave(LWORD,LETEXPR);
- XPput(args, yylval.cp);
- break;
- }
-#endif /* KSH */
-
-#ifdef KSH
- case DBRACKET: /* [[ .. ]] */
- syniocf &= ~(KEYWORD|ALIAS);
- t = newtp(TDBRACKET);
- ACCEPT;
- {
- Test_env te;
-
- te.flags = TEF_DBRACKET;
- te.pos.av = &args;
- te.isa = dbtestp_isa;
- te.getopnd = dbtestp_getopnd;
- te.eval = dbtestp_eval;
- te.error = dbtestp_error;
-
- test_parse(&te);
- }
- break;
-#endif /* KSH */
-
- case FOR:
- case SELECT:
- t = newtp((c == FOR) ? TFOR : TSELECT);
- musthave(LWORD, ARRAYVAR);
- if (!is_wdvarname(yylval.cp, TRUE))
- yyerror("%s: bad identifier\n",
- c == FOR ? "for" : "select");
- t->str = str_save(ident, ATEMP);
- multiline_push(&old_multiline, c);
- t->vars = wordlist();
- t->left = dogroup();
- multiline_pop(&old_multiline);
- break;
-
- case WHILE:
- case UNTIL:
- multiline_push(&old_multiline, c);
- t = newtp((c == WHILE) ? TWHILE : TUNTIL);
- t->left = c_list();
- t->right = dogroup();
- multiline_pop(&old_multiline);
- break;
-
- case CASE:
- t = newtp(TCASE);
- musthave(LWORD, 0);
- t->str = yylval.cp;
- multiline_push(&old_multiline, c);
- t->left = caselist();
- multiline_pop(&old_multiline);
- break;
-
- case IF:
- multiline_push(&old_multiline, c);
- t = newtp(TIF);
- t->left = c_list();
- t->right = thenpart();
- musthave(FI, KEYWORD|ALIAS);
- multiline_pop(&old_multiline);
- break;
-
- case BANG:
- syniocf &= ~(KEYWORD|ALIAS);
- t = pipeline(0);
- if (t == (struct op *) 0)
- syntaxerr((char *) 0);
- t = block(TBANG, NOBLOCK, t, NOWORDS);
- break;
-
- case TIME:
- syniocf &= ~(KEYWORD|ALIAS);
- t = pipeline(0);
- t = block(TTIME, t, NOBLOCK, NOWORDS);
- break;
-
- case FUNCTION:
- musthave(LWORD, 0);
- t = function_body(yylval.cp, TRUE);
- break;
- }
-
- while ((iop = synio(syniocf)) != NULL) {
- if (iopn >= NUFILE)
- yyerror("too many redirections\n");
- iops[iopn++] = iop;
- }
-
- if (iopn == 0) {
- afree((void*) iops, ATEMP);
- t->ioact = NULL;
- } else {
- iops[iopn++] = NULL;
- iops = (struct ioword **) aresize((void*) iops,
- sizeofN(struct ioword *, iopn), ATEMP);
- t->ioact = iops;
- }
-
- if (t->type == TCOM || t->type == TDBRACKET) {
- XPput(args, NULL);
- t->args = (char **) XPclose(args);
- XPput(vars, NULL);
- t->vars = (char **) XPclose(vars);
- } else {
- XPfree(args);
- XPfree(vars);
- }
-
- return t;
-}
-
-static struct op *
-dogroup()
-{
- register int c;
- register struct op *list;
-
- c = token(CONTIN|KEYWORD|ALIAS);
- /* A {...} can be used instead of do...done for for/select loops
- * but not for while/until loops - we don't need to check if it
- * is a while loop because it would have been parsed as part of
- * the conditional command list...
- */
- if (c == DO)
- c = DONE;
- else if (c == '{')
- c = '}';
- else
- syntaxerr((char *) 0);
- list = c_list();
- musthave(c, KEYWORD|ALIAS);
- return list;
-}
-
-static struct op *
-thenpart()
-{
- register struct op *t;
-
- musthave(THEN, KEYWORD|ALIAS);
- t = newtp(0);
- t->left = c_list();
- if (t->left == NULL)
- syntaxerr((char *) 0);
- t->right = elsepart();
- return (t);
-}
-
-static struct op *
-elsepart()
-{
- register struct op *t;
-
- switch (token(KEYWORD|ALIAS|VARASN)) {
- case ELSE:
- if ((t = c_list()) == NULL)
- syntaxerr((char *) 0);
- return (t);
-
- case ELIF:
- t = newtp(TELIF);
- t->left = c_list();
- t->right = thenpart();
- return (t);
-
- default:
- REJECT;
- }
- return NULL;
-}
-
-static struct op *
-caselist()
-{
- register struct op *t, *tl;
- int c;
-
- c = token(CONTIN|KEYWORD|ALIAS);
- /* A {...} can be used instead of in...esac for case statements */
- if (c == IN)
- c = ESAC;
- else if (c == '{')
- c = '}';
- else
- syntaxerr((char *) 0);
- t = tl = NULL;
- while ((tpeek(CONTIN|KEYWORD|ESACONLY)) != c) { /* no ALIAS here */
- struct op *tc = casepart(c);
- if (tl == NULL)
- t = tl = tc, tl->right = NULL;
- else
- tl->right = tc, tl = tc;
- }
- musthave(c, KEYWORD|ALIAS);
- return (t);
-}
-
-static struct op *
-casepart(endtok)
- int endtok;
-{
- register struct op *t;
- register int c;
- XPtrV ptns;
-
- XPinit(ptns, 16);
- t = newtp(TPAT);
- c = token(CONTIN|KEYWORD); /* no ALIAS here */
- if (c != '(')
- REJECT;
- do {
- musthave(LWORD, 0);
- XPput(ptns, yylval.cp);
- } while ((c = token(0)) == '|');
- REJECT;
- XPput(ptns, NULL);
- t->vars = (char **) XPclose(ptns);
- musthave(')', 0);
-
- t->left = c_list();
- if ((tpeek(CONTIN|KEYWORD|ALIAS)) != endtok)
- musthave(BREAK, CONTIN|KEYWORD|ALIAS);
- return (t);
-}
-
-static struct op *
-function_body(name, ksh_func)
- char *name;
- int ksh_func; /* function foo { ... } vs foo() { .. } */
-{
- XString xs;
- char *xp, *p;
- struct op *t;
- int old_func_parse;
-
- Xinit(xs, xp, 16, ATEMP);
- for (p = name; ; ) {
- if ((*p == EOS && Xlength(xs, xp) == 0)
- || (*p != EOS && *p != CHAR && *p != QCHAR
- && *p != OQUOTE && *p != CQUOTE))
- {
- p = snptreef((char *) 0, 32, "%S", name);
- yyerror("%s: invalid function name\n", p);
- }
- Xcheck(xs, xp);
- if (*p == EOS) {
- Xput(xs, xp, '\0');
- break;
- } else if (*p == CHAR || *p == QCHAR) {
- Xput(xs, xp, p[1]);
- p += 2;
- } else
- p++; /* OQUOTE/CQUOTE */
- }
- t = newtp(TFUNCT);
- t->str = Xclose(xs, xp);
- t->u.ksh_func = ksh_func;
-
- /* Note that POSIX allows only compound statements after foo(), sh and
- * at&t ksh allow any command, go with the later since it shouldn't
- * break anything. However, for function foo, at&t ksh only accepts
- * an open-brace.
- */
- if (ksh_func) {
- musthave('{', CONTIN|KEYWORD|ALIAS); /* } */
- REJECT;
- }
-
- old_func_parse = e->flags & EF_FUNC_PARSE;
- e->flags |= EF_FUNC_PARSE;
- if ((t->left = get_command(CONTIN)) == (struct op *) 0) {
- /* create empty command so foo(): will work */
- t->left = newtp(TCOM);
- t->args = (char **) alloc(sizeof(char *), ATEMP);
- t->args[0] = (char *) 0;
- t->vars = (char **) alloc(sizeof(char *), ATEMP);
- t->vars[0] = (char *) 0;
- }
- if (!old_func_parse)
- e->flags &= ~EF_FUNC_PARSE;
-
- return t;
-}
-
-static char **
-wordlist()
-{
- register int c;
- XPtrV args;
-
- XPinit(args, 16);
- if ((c = token(CONTIN|KEYWORD|ALIAS)) != IN) {
- if (c != ';') /* non-POSIX, but at&t ksh accepts a ; here */
- REJECT;
- return NULL;
- }
- while ((c = token(0)) == LWORD)
- XPput(args, yylval.cp);
- if (c != '\n' && c != ';')
- syntaxerr((char *) 0);
- if (XPsize(args) == 0) {
- XPfree(args);
- return NULL;
- } else {
- XPput(args, NULL);
- return (char **) XPclose(args);
- }
-}
-
-/*
- * supporting functions
- */
-
-static struct op *
-block(type, t1, t2, wp)
- int type;
- struct op *t1, *t2;
- char **wp;
-{
- register struct op *t;
-
- t = newtp(type);
- t->left = t1;
- t->right = t2;
- t->vars = wp;
- return (t);
-}
-
-const struct tokeninfo {
- const char *name;
- short val;
- short reserved;
-} tokentab[] = {
- /* Reserved words */
- { "if", IF, TRUE },
- { "then", THEN, TRUE },
- { "else", ELSE, TRUE },
- { "elif", ELIF, TRUE },
- { "fi", FI, TRUE },
- { "case", CASE, TRUE },
- { "esac", ESAC, TRUE },
- { "for", FOR, TRUE },
-#ifdef KSH
- { "select", SELECT, TRUE },
-#endif /* KSH */
- { "while", WHILE, TRUE },
- { "until", UNTIL, TRUE },
- { "do", DO, TRUE },
- { "done", DONE, TRUE },
- { "in", IN, TRUE },
- { "function", FUNCTION, TRUE },
- { "time", TIME, TRUE },
- { "{", '{', TRUE },
- { "}", '}', TRUE },
- { "!", BANG, TRUE },
-#ifdef KSH
- { "[[", DBRACKET, TRUE },
-#endif /* KSH */
- /* Lexical tokens (0[EOF], LWORD and REDIR handled specially) */
- { "&&", LOGAND, FALSE },
- { "||", LOGOR, FALSE },
- { ";;", BREAK, FALSE },
-#ifdef KSH
- { "((", MDPAREN, FALSE },
- { "|&", COPROC, FALSE },
-#endif /* KSH */
- /* and some special cases... */
- { "newline", '\n', FALSE },
- { 0 }
-};
-
-void
-initkeywords()
-{
- register struct tokeninfo const *tt;
- register struct tbl *p;
-
- tinit(&keywords, APERM, 32); /* must be 2^n (currently 20 keywords) */
- for (tt = tokentab; tt->name; tt++) {
- if (tt->reserved) {
- p = tenter(&keywords, tt->name, hash(tt->name));
- p->flag |= DEFINED|ISSET;
- p->type = CKEYWD;
- p->val.i = tt->val;
- }
- }
-}
-
-static void
-syntaxerr(what)
- const char *what;
-{
- char redir[6]; /* 2<<- is the longest redirection, I think */
- const char *s;
- struct tokeninfo const *tt;
- int c;
-
- if (!what)
- what = "unexpected";
- REJECT;
- c = token(0);
- Again:
- switch (c) {
- case 0:
- if (multiline.on && multiline.start_token) {
- multiline.on = FALSE; /* avoid infinate loops */
- c = multiline.start_token;
- source->errline = multiline.start_line;
- what = "unmatched";
- goto Again;
- }
- /* don't quote the EOF */
- yyerror("syntax error: unexpected EOF\n");
- /*NOTREACHED*/
-
- case LWORD:
- s = snptreef((char *) 0, 32, "%S", yylval.cp);
- break;
-
- case REDIR:
- s = snptreef(redir, sizeof(redir), "%R", yylval.iop);
- break;
-
- default:
- for (tt = tokentab; tt->name; tt++)
- if (tt->val == c)
- break;
- if (tt->name)
- s = tt->name;
- else {
- if (c > 0 && c < 256) {
- redir[0] = c;
- redir[1] = '\0';
- } else
- shf_snprintf(redir, sizeof(redir),
- "?%d", c);
- s = redir;
- }
- }
- yyerror("syntax error: `%s' %s\n", s, what);
-}
-
-static void
-multiline_push(save, tok)
- struct multiline_state *save;
- int tok;
-{
- *save = multiline;
- multiline.on = TRUE;
- multiline.start_token = tok;
- multiline.start_line = source->line;
-}
-
-static void
-multiline_pop(saved)
- struct multiline_state *saved;
-{
- multiline = *saved;
-}
-
-static struct op *
-newtp(type)
- int type;
-{
- register struct op *t;
-
- t = (struct op *) alloc(sizeof(*t), ATEMP);
- t->type = type;
- t->u.evalflags = 0;
- t->args = t->vars = NULL;
- t->ioact = NULL;
- t->left = t->right = NULL;
- t->str = NULL;
- return (t);
-}
-
-struct op *
-compile(s)
- Source *s;
-{
- yynerrs = 0;
- multiline.on = s->type == SSTRING;
- multiline.start_token = 0;
- multiline.start_line = 0;
- herep = heres;
- source = s;
- yyparse();
- return outtree;
-}
-
-/* This kludge exists to take care of sh/at&t ksh oddity in which
- * the arguments of alias/export/readonly/typeset have no field
- * splitting, file globbing, or (normal) tilde expansion done.
- * at&t ksh seems to do something similar to this since
- * $ touch a=a; typeset a=[ab]; echo "$a"
- * a=[ab]
- * $ x=typeset; $x a=[ab]; echo "$a"
- * a=a
- * $
- */
-static int
-assign_command(s)
- char *s;
-{
- char c = *s;
-
- if (Flag(FPOSIX) || !*s)
- return 0;
- return (c == 'a' && strcmp(s, "alias") == 0)
- || (c == 'e' && strcmp(s, "export") == 0)
- || (c == 'r' && strcmp(s, "readonly") == 0)
- || (c == 't' && strcmp(s, "typeset") == 0);
-}
-
-/* Check if we are in the middle of reading an alias */
-static int
-inalias(s)
- struct source *s;
-{
- for (; s && s->type == SALIAS; s = s->next)
- if (!(s->flags & SF_ALIASEND))
- return 1;
- return 0;
-}
-
-
-#ifdef KSH
-/* Order important - indexed by Test_meta values
- * Note that ||, &&, ( and ) can't appear in as unquoted strings
- * in normal shell input, so these can be interpreted unambiguously
- * in the evaluation pass.
- */
-static const char dbtest_or[] = { CHAR, '|', CHAR, '|', EOS };
-static const char dbtest_and[] = { CHAR, '&', CHAR, '&', EOS };
-static const char dbtest_not[] = { CHAR, '!', EOS };
-static const char dbtest_oparen[] = { CHAR, '(', EOS };
-static const char dbtest_cparen[] = { CHAR, ')', EOS };
-const char *const dbtest_tokens[] = {
- dbtest_or, dbtest_and, dbtest_not,
- dbtest_oparen, dbtest_cparen
- };
-const char db_close[] = { CHAR, ']', CHAR, ']', EOS };
-const char db_lthan[] = { CHAR, '<', EOS };
-const char db_gthan[] = { CHAR, '>', EOS };
-
-/* Test if the current token is a whatever. Accepts the current token if
- * it is. Returns 0 if it is not, non-zero if it is (in the case of
- * TM_UNOP and TM_BINOP, the returned value is a Test_op).
- */
-static int
-dbtestp_isa(te, meta)
- Test_env *te;
- Test_meta meta;
-{
- int c = tpeek(ARRAYVAR | (meta == TM_BINOP ? 0 : CONTIN));
- int uqword = 0;
- char *save = (char *) 0;
- int ret = 0;
-
- /* unquoted word? */
- uqword = c == LWORD && *ident;
-
- if (meta == TM_OR)
- ret = c == LOGOR;
- else if (meta == TM_AND)
- ret = c == LOGAND;
- else if (meta == TM_NOT)
- ret = uqword && strcmp(yylval.cp, dbtest_tokens[(int) TM_NOT]) == 0;
- else if (meta == TM_OPAREN)
- ret = c == '(' /*)*/;
- else if (meta == TM_CPAREN)
- ret = c == /*(*/ ')';
- else if (meta == TM_UNOP || meta == TM_BINOP) {
- if (meta == TM_BINOP && c == REDIR
- && (yylval.iop->flag == IOREAD
- || yylval.iop->flag == IOWRITE))
- {
- ret = 1;
- save = wdcopy(yylval.iop->flag == IOREAD ?
- db_lthan : db_gthan, ATEMP);
- } else if (uqword && (ret = (int) test_isop(te, meta, ident)))
- save = yylval.cp;
- } else /* meta == TM_END */
- ret = uqword && strcmp(yylval.cp, db_close) == 0;
- if (ret) {
- ACCEPT;
- if (meta != TM_END) {
- if (!save)
- save = wdcopy(dbtest_tokens[(int) meta], ATEMP);
- XPput(*te->pos.av, save);
- }
- }
- return ret;
-}
-
-static const char *
-dbtestp_getopnd(te, op, do_eval)
- Test_env *te;
- Test_op op;
- int do_eval;
-{
- int c = tpeek(ARRAYVAR);
-
- if (c != LWORD)
- return (const char *) 0;
-
- ACCEPT;
- XPput(*te->pos.av, yylval.cp);
-
- return null;
-}
-
-static int
-dbtestp_eval(te, op, opnd1, opnd2, do_eval)
- Test_env *te;
- Test_op op;
- const char *opnd1;
- const char *opnd2;
- int do_eval;
-{
- return 1;
-}
-
-static void
-dbtestp_error(te, offset, msg)
- Test_env *te;
- int offset;
- const char *msg;
-{
- te->flags |= TEF_ERROR;
-
- if (offset < 0) {
- REJECT;
- /* Kludgy to say the least... */
- symbol = LWORD;
- yylval.cp = *(XPptrv(*te->pos.av) + XPsize(*te->pos.av)
- + offset);
- }
- syntaxerr(msg);
-}
-#endif /* KSH */
diff --git a/bin/pdksh/table.c b/bin/pdksh/table.c
deleted file mode 100644
index a390c172c77..00000000000
--- a/bin/pdksh/table.c
+++ /dev/null
@@ -1,239 +0,0 @@
-/* $OpenBSD: table.c,v 1.4 1997/06/19 13:58:47 kstailey Exp $ */
-
-/*
- * dynamic hashed associative table for commands and variables
- */
-
-#include "sh.h"
-
-#define INIT_TBLS 8 /* initial table size (power of 2) */
-
-static void texpand ARGS((struct table *tp, int nsize));
-static int tnamecmp ARGS((void *p1, void *p2));
-
-
-unsigned int
-hash(n)
- register const char * n;
-{
- register unsigned int h = 0;
-
- while (*n != '\0')
- h = 2*h + *n++;
- return h * 32821; /* scatter bits */
-}
-
-void
-tinit(tp, ap, tsize)
- register struct table *tp;
- register Area *ap;
- int tsize;
-{
- tp->areap = ap;
- tp->tbls = NULL;
- tp->size = tp->nfree = 0;
- if (tsize)
- texpand(tp, tsize);
-}
-
-static void
-texpand(tp, nsize)
- register struct table *tp;
- int nsize;
-{
- register int i;
- register struct tbl *tblp, **p;
- register struct tbl **ntblp, **otblp = tp->tbls;
- int osize = tp->size;
-
- ntblp = (struct tbl**) alloc(sizeofN(struct tbl *, nsize), tp->areap);
- for (i = 0; i < nsize; i++)
- ntblp[i] = NULL;
- tp->size = nsize;
- tp->nfree = 8*nsize/10; /* table can get 80% full */
- tp->tbls = ntblp;
- if (otblp == NULL)
- return;
- for (i = 0; i < osize; i++)
- if ((tblp = otblp[i]) != NULL)
- if ((tblp->flag&DEFINED)) {
- for (p = &ntblp[hash(tblp->name)
- & (tp->size-1)];
- *p != NULL; p--)
- if (p == ntblp) /* wrap */
- p += tp->size;
- *p = tblp;
- tp->nfree--;
- } else if (!(tblp->flag & FINUSE)) {
- afree((void*)tblp, tp->areap);
- }
- afree((void*)otblp, tp->areap);
-}
-
-struct tbl *
-tsearch(tp, n, h)
- register struct table *tp; /* table */
- register const char *n; /* name to enter */
- unsigned int h; /* hash(n) */
-{
- register struct tbl **pp, *p;
-
- if (tp->size == 0)
- return NULL;
-
- /* search for name in hashed table */
- for (pp = &tp->tbls[h & (tp->size-1)]; (p = *pp) != NULL; pp--) {
- if (*p->name == *n && strcmp(p->name, n) == 0
- && (p->flag&DEFINED))
- return p;
- if (pp == tp->tbls) /* wrap */
- pp += tp->size;
- }
-
- return NULL;
-}
-
-struct tbl *
-tenter(tp, n, h)
- register struct table *tp; /* table */
- register const char *n; /* name to enter */
- unsigned int h; /* hash(n) */
-{
- register struct tbl **pp, *p;
- register int len;
-
- if (tp->size == 0)
- texpand(tp, INIT_TBLS);
- Search:
- /* search for name in hashed table */
- for (pp = &tp->tbls[h & (tp->size-1)]; (p = *pp) != NULL; pp--) {
- if (*p->name == *n && strcmp(p->name, n) == 0)
- return p; /* found */
- if (pp == tp->tbls) /* wrap */
- pp += tp->size;
- }
-
- if (tp->nfree <= 0) { /* too full */
- texpand(tp, 2*tp->size);
- goto Search;
- }
-
- /* create new tbl entry */
- len = strlen(n) + 1;
- p = (struct tbl *) alloc(offsetof(struct tbl, name[0]) + len,
- tp->areap);
- p->flag = 0;
- p->type = 0;
- p->areap = tp->areap;
- p->u2.field = 0;
- p->u.array = (struct tbl *)0;
- memcpy(p->name, n, len);
-
- /* enter in tp->tbls */
- tp->nfree--;
- *pp = p;
- return p;
-}
-
-void
-tdelete(p)
- register struct tbl *p;
-{
- p->flag = 0;
-}
-
-void
-twalk(ts, tp)
- struct tstate *ts;
- struct table *tp;
-{
- ts->left = tp->size;
- ts->next = tp->tbls;
-}
-
-struct tbl *
-tnext(ts)
- struct tstate *ts;
-{
- while (--ts->left >= 0) {
- struct tbl *p = *ts->next++;
- if (p != NULL && (p->flag&DEFINED))
- return p;
- }
- return NULL;
-}
-
-static int
-tnamecmp(p1, p2)
- void *p1, *p2;
-{
- return strcmp(((struct tbl *)p1)->name, ((struct tbl *)p2)->name);
-}
-
-struct tbl **
-tsort(tp)
- register struct table *tp;
-{
- register int i;
- register struct tbl **p, **sp, **dp;
-
- p = (struct tbl **)alloc(sizeofN(struct tbl *, tp->size+1), ATEMP);
- sp = tp->tbls; /* source */
- dp = p; /* dest */
- for (i = 0; i < tp->size; i++)
- if ((*dp = *sp++) != NULL && (((*dp)->flag&DEFINED) ||
- ((*dp)->flag&ARRAY)))
- dp++;
- i = dp - p;
- qsortp((void**)p, (size_t)i, tnamecmp);
- p[i] = NULL;
- return p;
-}
-
-#ifdef PERF_DEBUG /* performance debugging */
-
-void tprintinfo ARGS((struct table *tp));
-
-void
-tprintinfo(tp)
- struct table *tp;
-{
- struct tbl *te;
- char *n;
- unsigned int h;
- int ncmp;
- int totncmp = 0, maxncmp = 0;
- int nentries = 0;
- struct tstate ts;
-
- shellf("table size %d, nfree %d\n", tp->size, tp->nfree);
- shellf(" Ncmp name\n");
- twalk(&ts, tp);
- while ((te = tnext(&ts))) {
- register struct tbl **pp, *p;
-
- h = hash(n = te->name);
- ncmp = 0;
-
- /* taken from tsearch() and added counter */
- for (pp = &tp->tbls[h & (tp->size-1)]; (p = *pp); pp--) {
- ncmp++;
- if (*p->name == *n && strcmp(p->name, n) == 0
- && (p->flag&DEFINED))
- break; /* return p; */
- if (pp == tp->tbls) /* wrap */
- pp += tp->size;
- }
- shellf(" %4d %s\n", ncmp, n);
- totncmp += ncmp;
- nentries++;
- if (ncmp > maxncmp)
- maxncmp = ncmp;
- }
- if (nentries)
- shellf(" %d entries, worst ncmp %d, avg ncmp %d.%02d\n",
- nentries, maxncmp,
- totncmp / nentries,
- (totncmp % nentries) * 100 / nentries);
-}
-#endif /* PERF_DEBUG */
diff --git a/bin/pdksh/table.h b/bin/pdksh/table.h
deleted file mode 100644
index 75215719c22..00000000000
--- a/bin/pdksh/table.h
+++ /dev/null
@@ -1,176 +0,0 @@
-/* $OpenBSD: table.h,v 1.3 1996/11/21 07:59:35 downsj Exp $ */
-
-/* $From: table.h,v 1.3 1994/05/31 13:34:34 michael Exp $ */
-
-/*
- * generic hashed associative table for commands and variables.
- */
-
-struct table {
- Area *areap; /* area to allocate entries */
- short size, nfree; /* hash size (always 2^^n), free entries */
- struct tbl **tbls; /* hashed table items */
-};
-
-struct tbl { /* table item */
- Tflag flag; /* flags */
- int type; /* command type (see below), base (if INTEGER),
- * or offset from val.s of value (if EXPORT) */
- Area *areap; /* area to allocate from */
- union {
- char *s; /* string */
- long i; /* integer */
- int (*f) ARGS((char **)); /* int function */
- struct op *t; /* "function" tree */
- } val; /* value */
- int index; /* index for an array */
- union {
- int field; /* field with for -L/-R/-Z */
- int errno_; /* CEXEC/CTALIAS */
- } u2;
- union {
- struct tbl *array; /* array values */
- char *fpath; /* temporary path to undef function */
- } u;
- char name[4]; /* name -- variable length */
-};
-
-/* common flag bits */
-#define ALLOC BIT(0) /* val.s has been allocated */
-#define DEFINED BIT(1) /* is defined in block */
-#define ISSET BIT(2) /* has value, vp->val.[si] */
-#define EXPORT BIT(3) /* exported variable/function */
-#define TRACE BIT(4) /* var: user flagged, func: execution tracing */
-/* (start non-common flags at 8) */
-/* flag bits used for variables */
-#define SPECIAL BIT(8) /* PATH, IFS, SECONDS, etc */
-#define INTEGER BIT(9) /* val.i contains integer value */
-#define RDONLY BIT(10) /* read-only variable */
-#define LOCAL BIT(11) /* for local typeset() */
-#define ARRAY BIT(13) /* array */
-#define LJUST BIT(14) /* left justify */
-#define RJUST BIT(15) /* right justify */
-#define ZEROFIL BIT(16) /* 0 filled if RJUSTIFY, strip 0s if LJUSTIFY */
-#define LCASEV BIT(17) /* convert to lower case */
-#define UCASEV_AL BIT(18)/* convert to upper case / autoload function */
-#define INT_U BIT(19) /* unsigned integer */
-#define INT_L BIT(20) /* long integer (no-op) */
-#define IMPORT BIT(21) /* flag to typeset(): no arrays, must have = */
-#define LOCAL_COPY BIT(22) /* with LOCAL - copy attrs from existing var */
-#define EXPRINEVAL BIT(23) /* contents currently being evaluated */
-#define EXPRLVALUE BIT(24) /* useable as lvalue (temp flag) */
-/* flag bits used for taliases/builtins/aliases/keywords/functions */
-#define KEEPASN BIT(8) /* keep command assignments (eg, var=x cmd) */
-#define FINUSE BIT(9) /* function being executed */
-#define FDELETE BIT(10) /* function deleted while it was executing */
-#define FKSH BIT(11) /* function defined with function x (vs x()) */
-#define SPEC_BI BIT(12) /* a POSIX special builtin */
-#define REG_BI BIT(13) /* a POSIX regular builtin */
-/* Attributes that can be set by the user (used to decide if an unset param
- * should be repoted by set/typeset). Does not include ARRAY or LOCAL.
- */
-#define USERATTRIB (EXPORT|INTEGER|RDONLY|LJUST|RJUST|ZEROFIL\
- |LCASEV|UCASEV_AL|INT_U|INT_L)
-
-/* command types */
-#define CNONE 0 /* undefined */
-#define CSHELL 1 /* built-in */
-#define CFUNC 2 /* function */
-#define CEXEC 4 /* executable command */
-#define CALIAS 5 /* alias */
-#define CKEYWD 6 /* keyword */
-#define CTALIAS 7 /* tracked alias */
-
-/* Flags for findcom()/comexec() */
-#define FC_SPECBI BIT(0) /* special builtin */
-#define FC_FUNC BIT(1) /* function builtin */
-#define FC_REGBI BIT(2) /* regular builtin */
-#define FC_UNREGBI BIT(3) /* un-regular builtin (!special,!regular) */
-#define FC_BI (FC_SPECBI|FC_REGBI|FC_UNREGBI)
-#define FC_PATH BIT(4) /* do path search */
-#define FC_DEFPATH BIT(5) /* use default path in path search */
-
-
-#define AF_ARGV_ALLOC 0x1 /* argv[] array allocated */
-#define AF_ARGS_ALLOCED 0x2 /* argument strings allocated */
-#define AI_ARGV(a, i) ((i) == 0 ? (a).argv[0] : (a).argv[(i) - (a).skip])
-#define AI_ARGC(a) ((a).argc_ - (a).skip)
-
-/* Argument info. Used for $#, $* for shell, functions, includes, etc. */
-struct arg_info {
- int flags; /* AF_* */
- char **argv;
- int argc_;
- int skip; /* first arg is argv[0], second is argv[1 + skip] */
-};
-
-/*
- * activation record for function blocks
- */
-struct block {
- Area area; /* area to allocate things */
- /*struct arg_info argi;*/
- char **argv;
- int argc;
- struct table vars; /* local variables */
- struct table funs; /* local functions */
-#if 1
- char * error; /* error handler */
- char * exit; /* exit handler */
-#else
- Trap error, exit;
-#endif
- struct block *next; /* enclosing block */
-};
-
-/*
- * Used by twalk() and tnext() routines.
- */
-struct tstate {
- int left;
- struct tbl **next;
-};
-
-
-EXTERN struct table taliases; /* tracked aliases */
-EXTERN struct table builtins; /* built-in commands */
-EXTERN struct table aliases; /* aliases */
-EXTERN struct table keywords; /* keywords */
-EXTERN struct table homedirs; /* homedir() cache */
-
-struct builtin {
- const char *name;
- int (*func) ARGS((char **));
-};
-
-/* these really are externs! Look in table.c for them */
-extern const struct builtin shbuiltins [], kshbuiltins [];
-
-/* var spec values */
-#define V_NONE 0
-#define V_PATH 1
-#define V_IFS 2
-#define V_SECONDS 3
-#define V_OPTIND 4
-#define V_MAIL 5
-#define V_MAILPATH 6
-#define V_MAILCHECK 7
-#define V_RANDOM 8
-#define V_HISTSIZE 9
-#define V_HISTFILE 10
-#define V_VISUAL 11
-#define V_EDITOR 12
-#define V_COLUMNS 13
-#define V_POSIXLY_CORRECT 14
-#define V_TMOUT 15
-#define V_TMPDIR 16
-
-/* values for set_prompt() */
-#define PS1 0 /* command */
-#define PS2 1 /* command continuation */
-
-EXTERN const char *path; /* PATH value */
-EXTERN const char *def_path; /* path to use if PATH not set */
-EXTERN char *tmpdir; /* TMPDIR value */
-EXTERN const char *prompt;
-EXTERN int cur_prompt; /* PS1 or PS2 */
diff --git a/bin/pdksh/tests/alias.t b/bin/pdksh/tests/alias.t
deleted file mode 100644
index 0db6a2594cd..00000000000
--- a/bin/pdksh/tests/alias.t
+++ /dev/null
@@ -1,91 +0,0 @@
-name: alias-1
-description:
- Check that recursion is detected/avoided in aliases.
-stdin:
- alias fooBar=fooBar
- fooBar
- exit 0
-expected-stderr-pattern:
- /fooBar.*not found.*/
----
-
-name: alias-2
-description:
- Check that recursion is detected/avoided in aliases.
-stdin:
- alias fooBar=barFoo
- alias barFoo=fooBar
- fooBar
- barFoo
- exit 0
-expected-stderr-pattern:
- /fooBar.*not found.*\n.*barFoo.*not found/
----
-
-name: alias-3
-description:
- Check that recursion is detected/avoided in aliases.
-stdin:
- alias Echo='echo '
- alias fooBar=barFoo
- alias barFoo=fooBar
- Echo fooBar
- unalias barFoo
- Echo fooBar
-expected-stdout:
- fooBar
- barFoo
----
-
-name: alias-4
-description:
- Check that alias expansion isn't done on keywords (in keyword
- postitions).
-stdin:
- alias Echo='echo '
- alias while=While
- while false; do echo hi ; done
- Echo while
-expected-stdout:
- While
----
-
-name: alias-5
-description:
- Check that alias expansion done after alias with trailing space.
-stdin:
- alias Echo='echo '
- alias foo='bar stuff '
- alias bar='Bar1 Bar2 '
- alias stuff='Stuff'
- alias blah='Blah'
- Echo foo blah
-expected-stdout:
- Bar1 Bar2 Stuff Blah
----
-
-name: alias-6
-description:
- Check that alias expansion done after alias with trailing space.
-stdin:
- alias Echo='echo '
- alias foo='bar bar'
- alias bar='Bar '
- alias blah=Blah
- Echo foo blah
-expected-stdout:
- Bar Bar Blah
----
-
-name: alias-7
-description:
- Check that alias expansion done after alias with trailing space
- after a keyword.
-stdin:
- alias X='case '
- alias Y=Z
- X Y in 'Y') echo is y ;; Z) echo is z ; esac
-expected-stdout:
- is z
----
-
diff --git a/bin/pdksh/tests/arith.t b/bin/pdksh/tests/arith.t
deleted file mode 100644
index e18ea2e9d78..00000000000
--- a/bin/pdksh/tests/arith.t
+++ /dev/null
@@ -1,79 +0,0 @@
-name: arith-lazy-1
-description:
- Check that only one side of ternary operator is evaluated
-stdin:
- x=i+=2
- y=j+=2
- typeset -i i=1 j=1
- echo $((1 ? 20 : (x+=2)))
- echo $i,$x
- echo $((0 ? (y+=2) : 30))
- echo $j,$y
-expected-stdout:
- 20
- 1,i+=2
- 30
- 1,j+=2
----
-
-name: arith-lazy-2
-description:
- Check that assignments not done on non-evaluated side of ternary
- operator
-stdin:
- x=i+=2
- y=j+=2
- typeset -i i=1 j=1
- echo $((1 ? 20 : (x+=2)))
- echo $i,$x
- echo $((0 ? (y+=2) : 30))
- echo $i,$y
-expected-stdout:
- 20
- 1,i+=2
- 30
- 1,j+=2
----
-
-name: arith-ternary-prec-1
-description:
- Check precidance of ternary operator vs assignment
-stdin:
- typeset -i x=2
- y=$((1 ? 20 : x+=2))
-expected-exit: e != 0
-expected-stderr-pattern:
- /.*:.*1 \? 20 : x\+=2.*lvalue.*\n$/
----
-
-name: arith-ternary-prec-2
-description:
- Check precidance of ternary operator vs assignment
-stdin:
- typeset -i x=2
- echo $((0 ? x+=2 : 20))
-expected-stdout:
- 20
----
-
-name: arith-div-assoc-1
-description:
- Check associativity of division operator
-stdin:
- echo $((20 / 2 / 2))
-expected-stdout:
- 5
----
-
-name: arith-assop-assoc-1
-description:
- Check associativity of assignment-operator operator
-stdin:
- typeset -i i=1 j=2 k=3
- echo $((i += j += k))
- echo $i,$j,$k
-expected-stdout:
- 6
- 6,5,3
----
-
diff --git a/bin/pdksh/tests/bksl-nl.t b/bin/pdksh/tests/bksl-nl.t
deleted file mode 100644
index 3fb92ff53b5..00000000000
--- a/bin/pdksh/tests/bksl-nl.t
+++ /dev/null
@@ -1,339 +0,0 @@
-#
-# These tests deal with how \newline is handled in various situations. The
-# first group of tests are places where it shouldn't be collapsed, the next
-# group of tests are places where it should be collapsed.
-#
-name: bksl-nl-ign-1
-description:
- Check that \newline is not collasped after #
-stdin:
- echo hi #there \
- echo folks
-expected-stdout:
- hi
- folks
----
-
-name: bksl-nl-ign-2
-description:
- Check that \newline is not collasped inside single quotes
-stdin:
- echo 'hi \
- there'
- echo folks
-expected-stdout:
- hi \
- there
- folks
----
-
-name: bksl-nl-ign-3
-description:
- Check that \newline is not collasped inside single quotes
-stdin:
- cat << \EOF
- hi \
- there
- EOF
-expected-stdout:
- hi \
- there
----
-
-name: blsk-nl-ign-4
-description:
- Check interaction of aliases, single quotes and here-documents
- with backslash-newline
- (don't know what posix has to say about this)
-stdin:
- a=2
- alias x='echo hi
- cat << "EOF"
- foo\
- bar
- some'
- x
- more\
- stuff$a
- EOF
-expected-stdout:
- hi
- foo\
- bar
- some
- more\
- stuff$a
----
-
-name: blsk-nl-ign-5
-description:
- Check what happens with backslash at end of input
- (the old bourne shell trashes them; so do we)
-stdin: !
- echo `echo foo\\`bar
- echo hi\
-expected-stdout:
- foobar
- hi
----
-
-
-#
-# Places \newline should be collapsed
-#
-name: bksl-nl-1
-description:
- Check that \newline is collasped before, in the middle of, and
- after words
-stdin:
- \
- echo hi\
- There, \
- folks
-expected-stdout:
- hiThere, folks
----
-
-name: bksl-nl-2
-description:
- Check that \newline is collasped in $ sequences
- (ksh93 fails this)
-stdin:
- a=12
- ab=19
- echo $\
- a
- echo $a\
- b
- echo $\
- {a}
- echo ${a\
- b}
- echo ${ab\
- }
-expected-stdout:
- 12
- 19
- 12
- 19
- 19
----
-
-name: bksl-nl-3
-description:
- Check that \newline is collasped in $(..) and `...` sequences
- (ksh93 fails this)
-stdin:
- echo $\
- (echo foobar1)
- echo $(\
- echo foobar2)
- echo $(echo foo\
- bar3)
- echo $(echo foobar4\
- )
- echo `
- echo stuff1`
- echo `echo st\
- uff2`
-expected-stdout:
- foobar1
- foobar2
- foobar3
- foobar4
- stuff1
- stuff2
----
-
-name: bksl-nl-4
-description:
- Check that \newline is collasped in $((..)) sequences
- (ksh93 fails this)
-stdin:
- echo $\
- ((1+2))
- echo $(\
- (1+2+3))
- echo $((\
- 1+2+3+4))
- echo $((1+\
- 2+3+4+5))
- echo $((1+2+3+4+5+6)\
- )
-expected-stdout:
- 3
- 6
- 10
- 15
- 21
----
-
-name: bksl-nl-5
-description:
- Check that \newline is collasped in double quoted strings
-stdin:
- echo "\
- hi"
- echo "foo\
- bar"
- echo "folks\
- "
-expected-stdout:
- hi
- foobar
- folks
----
-
-name: bksl-nl-6
-description:
- Check that \newline is collasped in here document delimiters
- (ksh93 fails second part of this)
-stdin:
- a=12
- cat << EO\
- F
- a=$a
- foo\
- bar
- EOF
- cat << E_O_F
- foo
- E_O_\
- F
- echo done
-expected-stdout:
- a=12
- foobar
- foo
- done
----
-
-name: bksl-nl-7
-description:
- Check that \newline is collasped in double-quoted here-document
- delimiter.
-stdin:
- a=12
- cat << "EO\
- F"
- a=$a
- foo\
- bar
- EOF
- echo done
-expected-stdout:
- a=$a
- foo\
- bar
- done
----
-
-name: bksl-nl-8
-description:
- Check that \newline is collasped in various 2+ character tokens
- delimiter.
- (ksh93 fails this)
-stdin:
- echo hi &\
- & echo there
- echo foo |\
- | echo bar
- cat <\
- < EOF
- stuff
- EOF
- cat <\
- <\
- - EOF
- more stuff
- EOF
- cat <<\
- EOF
- abcdef
- EOF
- echo hi >\
- > /dev/null
- echo $?
- i=1
- case $i in
- (\
- x|\
- 1\
- ) echo hi;\
- ;
- (*) echo oops
- esac
-expected-stdout:
- hi
- there
- foo
- stuff
- more stuff
- abcdef
- 0
- hi
----
-
-name: blsk-nl-9
-description:
- Check that \ at the end of an alias is collapsed when followed
- by a newline
- (don't know what posix has to say about this)
-stdin:
- alias x='echo hi\'
- x
- echo there
-expected-stdout:
- hiecho there
----
-
-name: blsk-nl-10
-description:
- Check that \newline in a keyword is collapsed
-stdin:
- i\
- f true; then\
- echo pass; el\
- se echo fail; fi
-expected-stdout:
- pass
----
-
-#
-# Places \newline should be collapsed (ksh extensions)
-#
-
-name: blsk-nl-ksh-1
-description:
- Check that \newline is collapsed in extended globbing
- (ksh93 fails this)
-stdin:
- xxx=foo
- case $xxx in
- (f*\
- (\
- o\
- )\
- ) echo ok ;;
- *) echo bad
- esac
-expected-stdout:
- ok
----
-
-name: blsk-nl-ksh-2
-description:
- Check that \newline is collapsed in ((...)) expressions
- (ksh93 fails this)
-stdin:
- i=1
- (\
- (\
- i=i+2\
- )\
- )
- echo $i
-expected-stdout:
- 3
----
-
diff --git a/bin/pdksh/tests/brkcont.t b/bin/pdksh/tests/brkcont.t
deleted file mode 100644
index 1eb9c2581c9..00000000000
--- a/bin/pdksh/tests/brkcont.t
+++ /dev/null
@@ -1,195 +0,0 @@
-name: break-1
-description:
- See if break breaks out of loops
-stdin:
- for i in a b c; do echo $i; break; echo bad-$i; done
- echo end-1
- for i in a b c; do echo $i; break 1; echo bad-$i; done
- echo end-2
- for i in a b c; do
- for j in x y z; do
- echo $i:$j
- break
- echo bad-$i
- done
- echo end-$i
- done
- echo end-3
-expected-stdout:
- a
- end-1
- a
- end-2
- a:x
- end-a
- b:x
- end-b
- c:x
- end-c
- end-3
----
-
-name: break-2
-description:
- See if break breaks out of nested loops
-stdin:
- for i in a b c; do
- for j in x y z; do
- echo $i:$j
- break 2
- echo bad-$i
- done
- echo end-$i
- done
- echo end
-expected-stdout:
- a:x
- end
----
-
-
-name: break-3
-description:
- What if break used outside of any loops
- (ksh88,ksh93 don't print error messages here)
-stdin:
- break
-expected-stderr-pattern:
- /.*break.*/
----
-
-
-name: break-4
-description:
- What if break N used when only N-1 loops
- (ksh88,ksh93 don't print error messages here)
-stdin:
- for i in a b c; do echo $i; break 2; echo bad-$i; done
- echo end
-expected-stdout:
- a
- end
-expected-stderr-pattern:
- /.*break.*/
----
-
-
-name: break-5
-description:
- Error if break argument isn't a number
-stdin:
- for i in a b c; do echo $i; break abc; echo more-$i; done
- echo end
-expected-stdout:
- a
-expected-exit: e != 0
-expected-stderr-pattern:
- /.*break.*/
----
-
-
-name: continue-1
-description:
- See if continue continues loops
-stdin:
- for i in a b c; do echo $i; continue; echo bad-$i ; done
- echo end-1
- for i in a b c; do echo $i; continue 1; echo bad-$i; done
- echo end-2
- for i in a b c; do
- for j in x y z; do
- echo $i:$j
- continue
- echo bad-$i-$j
- done
- echo end-$i
- done
- echo end-3
-expected-stdout:
- a
- b
- c
- end-1
- a
- b
- c
- end-2
- a:x
- a:y
- a:z
- end-a
- b:x
- b:y
- b:z
- end-b
- c:x
- c:y
- c:z
- end-c
- end-3
----
-
-
-name: continue-2
-description:
- See if continue breaks out of nested loops
-stdin:
- for i in a b c; do
- for j in x y z; do
- echo $i:$j
- continue 2
- echo bad-$i-$j
- done
- echo end-$i
- done
- echo end
-expected-stdout:
- a:x
- b:x
- c:x
- end
----
-
-
-name: continue-3
-description:
- What if continue used outside of any loops
- (ksh88,ksh93 don't print error messages here)
-stdin:
- continue
-expected-stderr-pattern:
- /.*continue.*/
----
-
-
-name: continue-4
-description:
- What if continue N used when only N-1 loops
- (ksh88,ksh93 don't print error messages here)
-stdin:
- for i in a b c; do echo $i; continue 2; echo bad-$i; done
- echo end
-expected-stdout:
- a
- b
- c
- end
-expected-stderr-pattern:
- /.*continue.*/
----
-
-
-name: continue-5
-description:
- Error if continue argument isn't a number
-stdin:
- for i in a b c; do echo $i; continue abc; echo more-$i; done
- echo end
-expected-stdout:
- a
-expected-exit: e != 0
-expected-stderr-pattern:
- /.*continue.*/
----
-
-
diff --git a/bin/pdksh/tests/cdhist.t b/bin/pdksh/tests/cdhist.t
deleted file mode 100644
index 720f7d60bcc..00000000000
--- a/bin/pdksh/tests/cdhist.t
+++ /dev/null
@@ -1,160 +0,0 @@
-name: cd-history
-description:
- Test someone's CD history package (uses arrays)
-stdin:
- # go to known place before doing anything
- cd /
-
- alias cd=_cd
- function _cd
- {
- typeset -i cdlen i
- typeset t
-
- if [ $# -eq 0 ]
- then
- set -- $HOME
- fi
-
- if [ "$CDHISTFILE" -a -r "$CDHISTFILE" ] # if directory history exists
- then
- typeset CDHIST
- i=-1
- while read -r t # read directory history file
- do
- CDHIST[i=i+1]=$t
- done <$CDHISTFILE
- fi
-
- if [ "${CDHIST[0]}" != "$PWD" -a "$PWD" != "" ]
- then
- _cdins # insert $PWD into cd history
- fi
-
- cdlen=${#CDHIST[*]} # number of elements in history
-
- case "$@" in
- -) # cd to new dir
- if [ "$OLDPWD" = "" ] && ((cdlen>1))
- then
- 'print' ${CDHIST[1]}
- 'cd' ${CDHIST[1]}
- _pwd
- else
- 'cd' $@
- _pwd
- fi
- ;;
- -l) # print directory list
- typeset -R3 num
- ((i=cdlen))
- while (((i=i-1)>=0))
- do
- num=$i
- 'print' "$num ${CDHIST[i]}"
- done
- return
- ;;
- -[0-9]|-[0-9][0-9]) # cd to dir in list
- if (((i=${1#-})<cdlen))
- then
- 'print' ${CDHIST[i]}
- 'cd' ${CDHIST[i]}
- _pwd
- else
- 'cd' $@
- _pwd
- fi
- ;;
- -*) # cd to matched dir in list
- t=${1#-}
- i=1
- while ((i<cdlen))
- do
- case ${CDHIST[i]} in
- *$t*)
- 'print' ${CDHIST[i]}
- 'cd' ${CDHIST[i]}
- _pwd
- break
- ;;
- esac
- ((i=i+1))
- done
- if ((i>=cdlen))
- then
- 'cd' $@
- _pwd
- fi
- ;;
- *) # cd to new dir
- 'cd' $@
- _pwd
- ;;
- esac
-
- _cdins # insert $PWD into cd history
-
- if [ "$CDHISTFILE" ]
- then
- cdlen=${#CDHIST[*]} # number of elements in history
-
- i=0
- while ((i<cdlen))
- do
- 'print' -r ${CDHIST[i]} # update directory history
- ((i=i+1))
- done >$CDHISTFILE
- fi
- }
-
- function _cdins # insert $PWD into cd history
- { # meant to be called only by _cd
- typeset -i i
-
- ((i=0))
- while ((i<${#CDHIST[*]})) # see if dir is already in list
- do
- if [ "${CDHIST[$i]}" = "$PWD" ]
- then
- break
- fi
- ((i=i+1))
- done
-
- if ((i>22)) # limit max size of list
- then
- i=22
- fi
-
- while (((i=i-1)>=0)) # bump old dirs in list
- do
- CDHIST[i+1]=${CDHIST[i]}
- done
-
- CDHIST[0]=$PWD # insert new directory in list
- }
-
-
- function _pwd
- {
- if [ -n "$ECD" ]
- then
- pwd 1>&6
- fi
- }
- # Start of test
- cd /tmp
- cd /bin
- cd /etc
- cd -
- cd -2
- cd -l
-expected-stdout:
- /bin
- /tmp
- 3 /
- 2 /etc
- 1 /bin
- 0 /tmp
----
diff --git a/bin/pdksh/tests/eglob.t b/bin/pdksh/tests/eglob.t
deleted file mode 100644
index ea69f635fcf..00000000000
--- a/bin/pdksh/tests/eglob.t
+++ /dev/null
@@ -1,138 +0,0 @@
-name: eglob-bad-1
-description:
- Check that globbing isn't done when glob has syntax error
-perl-setup:
- &touch("abcx", "abcz", "bbc");
-stdin:
- echo !([*)*
- echo +(a|b[)*
-expected-stdout:
- !([*)*
- +(a|b[)*
----
-
-name: eglob-bad-2
-description:
- Check that globbing isn't done when glob has syntax error
- (at&t ksh fails this test)
-perl-setup:
- &touch("abcx", "abcz", "bbc");
-stdin:
- echo [a*(]*)z
-expected-stdout:
- [a*(]*)z
----
-
-name: eglob-infinite-plus
-description:
- Check that shell doesn't go into infinite loop expanding +(...)
- expressions.
-perl-setup:
- &touch("abc");
-time-limit: 3
-stdin:
- echo +()c
- echo +()x
- echo +(*)c
- echo +(*)x
-expected-stdout:
- +()c
- +()x
- abc
- +(*)x
----
-
-name: eglob-subst-1
-description:
- Check that eglobbing isn't done on substitution results
-perl-setup:
- &touch("abc");
-stdin:
- x='@(*)'
- echo $x
-expected-stdout:
- @(*)
----
-
-name: eglob-nomatch-1
-description:
- Check that the pattern doesn't match
-stdin:
- echo no-file+(a|b)stuff
- echo no-file+(a*(c)|b)stuff
-expected-stdout:
- no-file+(a|b)stuff
- no-file+(a*(c)|b)stuff
----
-
-name: eglob-match-1
-description:
- Check that the pattern matches correctly
-perl-setup:
- &touch("abd", "acd");
-stdin:
- echo a+(b|c)d
- echo a!(@(b|B))d
- echo a[b*(foo|bar)]d
-expected-stdout:
- abd acd
- acd
- abd
----
-
-name: eglob-case-1
-description:
- Simple negation tests
-stdin:
- case foo in !(foo|bar)) echo yes;; *) echo no;; esac
- case bar in !(foo|bar)) echo yes;; *) echo no;; esac
-expected-stdout:
- no
- no
----
-
-name: eglob-case-2
-description:
- Simple kleene tests
-stdin:
- case foo in *(a|b[)) echo yes;; *) echo no;; esac
- case foo in *(a|b[)|f*) echo yes;; *) echo no;; esac
- case '*(a|b[)' in *(a|b[)) echo yes;; *) echo no;; esac
-expected-stdout:
- no
- yes
- yes
----
-
-name: eglob-trim-1
-description:
- Eglobing in trim expressions...
- (at&t ksh fails this - docs say # matches shortest string, ## matches
- longest...)
-stdin:
- x=abcdef
- echo 1: ${x#a|abc}
- echo 2: ${x##a|abc}
- echo 3: ${x%def|f}
- echo 4: ${x%%f|def}
-expected-stdout:
- 1: bcdef
- 2: def
- 3: abcde
- 4: abc
----
-
-name: eglob-trim-2
-description:
- Check eglobing works in trims...
-stdin:
- x=abcdef
- echo ${x#*(a|b)cd}
- echo "${x#*(a|b)cd}"
- echo ${x#"*(a|b)cd"}
-expected-stdout:
- ef
- ef
- abcdef
----
-
diff --git a/bin/pdksh/tests/glob.t b/bin/pdksh/tests/glob.t
deleted file mode 100644
index c7d8e26808d..00000000000
--- a/bin/pdksh/tests/glob.t
+++ /dev/null
@@ -1,96 +0,0 @@
-name: glob-bad-1
-description:
- Check that globbing isn't done when glob has syntax error
-perl-setup:
- mkdir("[x", 0777) || die "couldn't make directory [x - $!\n";
- &touch("[x/foo");
-stdin:
- echo [*
- echo *[x
- echo [x/*
-expected-stdout:
- [*
- *[x
- [x/foo
----
-
-name: glob-bad-2
-description:
- Check that symbolic links aren't stat()'d
-perl-setup:
- mkdir("dir", 0777) || die "couldn't make directory dir - $!\n";
- &touch("dir/abc");
- symlink("non-existent-file", "dir/abc");
-stdin:
- echo d*/*
- echo d*/abc
-expected-stdout:
- dir/abc
- dir/abc
----
-
-name: glob-range-1
-description:
- Test range matching
-perl-setup:
- &touch(".bc", "abc", "bbc", "cbc", "-bc");
-stdin:
- echo [ab-]*
- echo [-ab]*
- echo [!-ab]*
- echo [!ab]*
- echo []ab]*
-expected-stdout:
- -bc abc bbc
- -bc abc bbc
- cbc
- -bc cbc
- abc bbc
----
-
-name: glob-range-2
-description:
- Test range matching
- (at&t ksh fails this; POSIX says invalid)
-perl-setup:
- &touch("abc");
-stdin:
- echo [a--]*
-expected-stdout:
- [a--]*
----
-
-name: glob-range-3
-description:
- Check that globbing matches the right things...
-perl-setup:
- &touch("a\302c");
-stdin:
- echo a[Á-Ú]*
-expected-stdout:
- aÂc
----
-
-name: glob-range-4
-description:
- Results unspecified according to POSIX
-perl-setup:
- &touch(".bc");
-stdin:
- echo [a.]*
-expected-stdout:
- [a.]*
----
-
-name: glob-range-5
-description:
- Results unspecified according to POSIX
- (at&t ksh treats this like [a-cc-e]*)
-perl-setup:
- &touch("abc", "bbc", "cbc", "dbc", "ebc", "-bc");
-stdin:
- echo [a-c-e]*
-expected-stdout:
- -bc abc bbc cbc ebc
----
-
diff --git a/bin/pdksh/tests/heredoc.t b/bin/pdksh/tests/heredoc.t
deleted file mode 100644
index 21feb925cea..00000000000
--- a/bin/pdksh/tests/heredoc.t
+++ /dev/null
@@ -1,144 +0,0 @@
-name: heredoc-1
-description:
- Check ordering/content of redundent here documents.
-stdin:
- cat << EOF1 << EOF2
- hi
- EOF1
- there
- EOF2
-expected-stdout:
- there
----
-
-name: heredoc-2
-description:
- Check quoted here-doc is protected.
-stdin:
- a=foo
- cat << 'EOF'
- hi\
- there$a
- stuff
- EO\
- F
- EOF
-expected-stdout:
- hi\
- there$a
- stuff
- EO\
- F
----
-
-name: heredoc-3
-description:
- Check that newline isn't needed after heredoc-delimiter marker.
-stdin: !
- cat << EOF
- hi
- there
- EOF
-expected-stdout:
- hi
- there
----
-
-name: heredoc-4
-description:
- Check that an error occurs if the heredoc-delimiter is missing.
-stdin: !
- cat << EOF
- hi
- there
-expected-exit: e > 0
-expected-stderr-pattern: /.*/
----
-
-name: heredoc-5
-description:
- Check that backslash quotes a $, ` and \ and kills a \newline
-stdin:
- a=BAD
- b=ok
- cat << EOF
- h\${a}i
- h\\${b}i
- th\`echo not-run\`ere
- th\\`echo is-run`ere
- fol\\ks
- more\\
- last \
- line
- EOF
-expected-stdout:
- h${a}i
- h\oki
- th`echo not-run`ere
- th\is-runere
- fol\ks
- more\
- last line
----
-
-name: heredoc-6
-description:
- Check that \newline in initial here-delim word doesn't imply
- a quoted here-doc.
-stdin:
- a=i
- cat << EO\
- F
- h$a
- there
- EOF
-expected-stdout:
- hi
- there
----
-
-name: heredoc-7
-description:
- Check that double quoted $ expressions in here delimiters are
- not expanded and match the delimiter.
- POSIX says only quote removal is applied to the delimiter.
-stdin:
- a=b
- cat << "E$a"
- hi
- h$a
- hb
- E$a
- echo done
-expected-stdout:
- hi
- h$a
- hb
- done
----
-
-name: heredoc-8
-description:
- Check that double quoted escaped $ expressions in here
- delimiters are not expanded and match the delimiter.
- POSIX says only quote removal is applied to the delimiter
- (\ counts as a quote).
-stdin:
- a=b
- cat << "E\$a"
- hi
- h$a
- h\$a
- hb
- h\b
- E$a
- echo done
-expected-stdout:
- hi
- h$a
- h\$a
- hb
- h\b
- done
----
-
diff --git a/bin/pdksh/tests/history.t b/bin/pdksh/tests/history.t
deleted file mode 100644
index 078aeb60969..00000000000
--- a/bin/pdksh/tests/history.t
+++ /dev/null
@@ -1,529 +0,0 @@
-# Not tested yet:
-# - commands in history file are not numbered negatively
-# (and a few hundred other things)
-
-name: history-basic
-description:
- See if we can test history at all
-arguments: !-i!
-env-setup: !ENV=./Env!HISTFILE=hist.file!
-perl-setup: system("echo PS1=X > Env");
-stdin:
- echo hi
- fc -l
-expected-stdout:
- hi
- 1 echo hi
-expected-stderr-pattern:
- /^X*$/
----
-
-name: history-e-minus-1
-description:
- Check if more recent command is executed
-arguments: !-i!
-env-setup: !ENV=./Env!HISTFILE=hist.file!
-perl-setup: system("echo PS1=X > Env");
-stdin:
- echo hi
- echo there
- fc -e -
-expected-stdout:
- hi
- there
- there
-expected-stderr-pattern:
- /^X*echo there\nX*$/
----
-
-name: history-e-minus-2
-description:
- Check that repeated command is printed before command
- is re-executed.
-arguments: !-i!
-env-setup: !ENV=./Env!HISTFILE=hist.file!
-perl-setup: system("echo PS1=X > Env");
-stdin:
- exec 2>&1
- echo hi
- echo there
- fc -e -
-expected-stdout-pattern:
- /X*hi\nX*there\nX*echo there\nthere\nX*/
-expected-stderr-pattern:
- /^X*$/
----
-
-name: history-e-minus-3
-description:
- fc -e - fails when there is no history
- (ksh93 has a bug that causes this to fail)
- (ksh88 loops on this)
-arguments: !-i!
-env-setup: !ENV=./Env!HISTFILE=hist.file!
-perl-setup: system("echo PS1=X > Env");
-stdin:
- fc -e -
- echo ok
-expected-stdout:
- ok
-expected-stderr-pattern:
- /^X*.*:.*history.*\nX*$/
----
-
-name: history-e-minus-4
-description:
- Check if "fc -e -" command output goes to stdout.
-arguments: !-i!
-env-setup: !ENV=./Env!HISTFILE=hist.file!
-perl-setup: system("echo PS1=X > Env");
-stdin:
- echo abc
- fc -e - | (read x; echo "A $x")
- echo ok
-expected-stdout:
- abc
- A abc
- ok
-expected-stderr-pattern:
- /^X*echo abc\nX*/
----
-
-name: history-e-minus-5
-description:
- fc is replaced in history by new command.
-arguments: !-i!
-env-setup: !ENV=./Env!HISTFILE=hist.file!
-perl-setup: system("echo PS1=X > Env");
-stdin:
- echo abc def
- echo ghi jkl
- fc -e - echo
- fc -l 2 4
-expected-stdout:
- abc def
- ghi jkl
- ghi jkl
- 2 echo ghi jkl
- 3 echo ghi jkl
- 4 fc -l 2 4
-expected-stderr-pattern:
- /^X*echo ghi jkl\nX*$/
----
-
-name: history-list-1
-description:
- List lists correct range
- (ksh88 fails 'cause it lists the fc command)
-arguments: !-i!
-env-setup: !ENV=./Env!HISTFILE=hist.file!
-perl-setup: system("echo PS1=X > Env");
-stdin:
- echo line 1
- echo line 2
- echo line 3
- fc -l -- -2
-expected-stdout:
- line 1
- line 2
- line 3
- 2 echo line 2
- 3 echo line 3
-expected-stderr-pattern:
- /^X*$/
----
-
-name: history-list-2
-description:
- Lists oldest history if given pre-historic number
- (ksh93 has a bug that causes this to fail)
- (ksh88 fails 'cause it lists the fc command)
-arguments: !-i!
-env-setup: !ENV=./Env!HISTFILE=hist.file!
-perl-setup: system("echo PS1=X > Env");
-stdin:
- echo line 1
- echo line 2
- echo line 3
- fc -l -- -40
-expected-stdout:
- line 1
- line 2
- line 3
- 1 echo line 1
- 2 echo line 2
- 3 echo line 3
-expected-stderr-pattern:
- /^X*$/
----
-
-name: history-list-3
-description:
- Can give number `options' to fc
-arguments: !-i!
-env-setup: !ENV=./Env!HISTFILE=hist.file!
-perl-setup: system("echo PS1=X > Env");
-stdin:
- echo line 1
- echo line 2
- echo line 3
- echo line 4
- fc -l -3 -2
-expected-stdout:
- line 1
- line 2
- line 3
- line 4
- 2 echo line 2
- 3 echo line 3
-expected-stderr-pattern:
- /^X*$/
----
-
-name: history-list-4
-description:
- -1 refers to previous command
-arguments: !-i!
-env-setup: !ENV=./Env!HISTFILE=hist.file!
-perl-setup: system("echo PS1=X > Env");
-stdin:
- echo line 1
- echo line 2
- echo line 3
- echo line 4
- fc -l -1 -1
-expected-stdout:
- line 1
- line 2
- line 3
- line 4
- 4 echo line 4
-expected-stderr-pattern:
- /^X*$/
----
-
-name: history-list-5
-description:
- List command stays in history
-arguments: !-i!
-env-setup: !ENV=./Env!HISTFILE=hist.file!
-perl-setup: system("echo PS1=X > Env");
-stdin:
- echo line 1
- echo line 2
- echo line 3
- echo line 4
- fc -l -1 -1
- fc -l -2 -1
-expected-stdout:
- line 1
- line 2
- line 3
- line 4
- 4 echo line 4
- 4 echo line 4
- 5 fc -l -1 -1
-expected-stderr-pattern:
- /^X*$/
----
-
-name: history-list-6
-description:
- HISTSIZE limits about of history kept.
- (ksh88 fails 'cause it lists the fc command)
-arguments: !-i!
-env-setup: !ENV=./Env!HISTFILE=hist.file!HISTSIZE=3!
-perl-setup: system("echo PS1=X > Env");
-stdin:
- echo line 1
- echo line 2
- echo line 3
- echo line 4
- echo line 5
- fc -l
-expected-stdout:
- line 1
- line 2
- line 3
- line 4
- line 5
- 4 echo line 4
- 5 echo line 5
-expected-stderr-pattern:
- /^X*$/
----
-
-name: history-list-7
-description:
- fc allows too old/new errors in range specification
-arguments: !-i!
-env-setup: !ENV=./Env!HISTFILE=hist.file!HISTSIZE=3!
-perl-setup: system("echo PS1=X > Env");
-stdin:
- echo line 1
- echo line 2
- echo line 3
- echo line 4
- echo line 5
- fc -l 1 30
-expected-stdout:
- line 1
- line 2
- line 3
- line 4
- line 5
- 4 echo line 4
- 5 echo line 5
- 6 fc -l 1 30
-expected-stderr-pattern:
- /^X*$/
----
-
-name: history-list-r-1
-description:
- test -r flag in history
-arguments: !-i!
-env-setup: !ENV=./Env!HISTFILE=hist.file!
-perl-setup: system("echo PS1=X > Env");
-stdin:
- echo line 1
- echo line 2
- echo line 3
- echo line 4
- echo line 5
- fc -l -r 2 4
-expected-stdout:
- line 1
- line 2
- line 3
- line 4
- line 5
- 4 echo line 4
- 3 echo line 3
- 2 echo line 2
-expected-stderr-pattern:
- /^X*$/
----
-
-name: history-list-r-2
-description:
- If first is newer than last, -r is implied.
-arguments: !-i!
-env-setup: !ENV=./Env!HISTFILE=hist.file!
-perl-setup: system("echo PS1=X > Env");
-stdin:
- echo line 1
- echo line 2
- echo line 3
- echo line 4
- echo line 5
- fc -l 4 2
-expected-stdout:
- line 1
- line 2
- line 3
- line 4
- line 5
- 4 echo line 4
- 3 echo line 3
- 2 echo line 2
-expected-stderr-pattern:
- /^X*$/
----
-
-name: history-list-r-3
-description:
- If first is newer than last, -r is cancelled.
-arguments: !-i!
-env-setup: !ENV=./Env!HISTFILE=hist.file!
-perl-setup: system("echo PS1=X > Env");
-stdin:
- echo line 1
- echo line 2
- echo line 3
- echo line 4
- echo line 5
- fc -l -r 4 2
-expected-stdout:
- line 1
- line 2
- line 3
- line 4
- line 5
- 2 echo line 2
- 3 echo line 3
- 4 echo line 4
-expected-stderr-pattern:
- /^X*$/
----
-
-name: history-subst-1
-description:
- Basic substitution
-arguments: !-i!
-env-setup: !ENV=./Env!HISTFILE=hist.file!
-perl-setup: system("echo PS1=X > Env");
-stdin:
- echo abc def
- echo ghi jkl
- fc -e - abc=AB 'echo a'
-expected-stdout:
- abc def
- ghi jkl
- AB def
-expected-stderr-pattern:
- /^X*echo AB def\nX*$/
----
-
-name: history-subst-2
-description:
- Does subst find previous command?
-arguments: !-i!
-env-setup: !ENV=./Env!HISTFILE=hist.file!
-perl-setup: system("echo PS1=X > Env");
-stdin:
- echo abc def
- echo ghi jkl
- fc -e - jkl=XYZQRT 'echo g'
-expected-stdout:
- abc def
- ghi jkl
- ghi XYZQRT
-expected-stderr-pattern:
- /^X*echo ghi XYZQRT\nX*$/
----
-
-name: history-subst-3
-description:
- Does subst find previous command when no arguments given
-arguments: !-i!
-env-setup: !ENV=./Env!HISTFILE=hist.file!
-perl-setup: system("echo PS1=X > Env");
-stdin:
- echo abc def
- echo ghi jkl
- fc -e - jkl=XYZQRT
-expected-stdout:
- abc def
- ghi jkl
- ghi XYZQRT
-expected-stderr-pattern:
- /^X*echo ghi XYZQRT\nX*$/
----
-
-name: history-subst-4
-description:
- Global substitutions work
- (ksh88 and ksh93 do not have -g option)
-arguments: !-i!
-env-setup: !ENV=./Env!HISTFILE=hist.file!
-perl-setup: system("echo PS1=X > Env");
-stdin:
- echo abc def asjj sadjhasdjh asdjhasd
- fc -e - -g a=FooBAR
-expected-stdout:
- abc def asjj sadjhasdjh asdjhasd
- FooBARbc def FooBARsjj sFooBARdjhFooBARsdjh FooBARsdjhFooBARsd
-expected-stderr-pattern:
- /^X*echo FooBARbc def FooBARsjj sFooBARdjhFooBARsdjh FooBARsdjhFooBARsd\nX*$/
----
-
-name: history-subst-5
-description:
- Make sure searches don't find current (fc) command
- (ksh88/ksh93 don't have the ? prefix thing so they fail this test)
-arguments: !-i!
-env-setup: !ENV=./Env!HISTFILE=hist.file!
-perl-setup: system("echo PS1=X > Env");
-stdin:
- echo abc def
- echo ghi jkl
- fc -e - abc=AB \?abc
-expected-stdout:
- abc def
- ghi jkl
- AB def
-expected-stderr-pattern:
- /^X*echo AB def\nX*$/
----
-
-name: history-ed-1
-description:
- Basic (ed) editing works (assumes you have generic ed editor
- that prints no prompts).
-arguments: !-i!
-env-setup: !ENV=./Env!HISTFILE=hist.file!
-perl-setup: system("echo PS1=X > Env");
-stdin:
- echo abc def
- fc echo
- s/abc/FOOBAR/
- w
- q
-expected-stdout:
- abc def
- 13
- 16
- FOOBAR def
-expected-stderr-pattern:
- /^X*echo FOOBAR def\nX*$/
----
-
-name: history-ed-2
-description:
- Correct command is edited when number given
-arguments: !-i!
-env-setup: !ENV=./Env!HISTFILE=hist.file!
-perl-setup: system("echo PS1=X > Env");
-stdin:
- echo line 1
- echo line 2 is here
- echo line 3
- echo line 4
- fc 2
- s/is here/is changed/
- w
- q
-expected-stdout:
- line 1
- line 2 is here
- line 3
- line 4
- 20
- 23
- line 2 is changed
-expected-stderr-pattern:
- /^X*echo line 2 is changed\nX*$/
----
-
-name: history-ed-3
-description:
- Newly created multi line commands show up as single command
- in history.
- (NOTE: will fail if using COMPLEX HISTORY compile time option)
- (ksh88 fails 'cause it lists the fc command)
-arguments: !-i!
-env-setup: !ENV=./Env!HISTFILE=hist.file!
-perl-setup: system("echo PS1=X > Env");
-stdin:
- echo abc def
- fc echo
- s/abc/FOOBAR/
- $a
- echo a new line
- .
- w
- q
- fc -l
-expected-stdout:
- abc def
- 13
- 32
- FOOBAR def
- a new line
- 1 echo abc def
- 2 echo FOOBAR def
- echo a new line
-expected-stderr-pattern:
- /^X*echo FOOBAR def\necho a new line\nX*$/
----
diff --git a/bin/pdksh/tests/ifs.t b/bin/pdksh/tests/ifs.t
deleted file mode 100644
index a927aa301fc..00000000000
--- a/bin/pdksh/tests/ifs.t
+++ /dev/null
@@ -1,162 +0,0 @@
-name: IFS-space-1
-description:
- Simple test, default IFS
-stdin:
- showargs() { for i; do echo -n " <$i>"; done; echo; }
- set -- A B C
- showargs 1 $*
- showargs 2 "$*"
- showargs 3 $@
- showargs 4 "$@"
-expected-stdout:
- <1> <A> <B> <C>
- <2> <A B C>
- <3> <A> <B> <C>
- <4> <A> <B> <C>
----
-
-name: IFS-colon-1
-description:
- Simple test, IFS=:
-stdin:
- showargs() { for i; do echo -n " <$i>"; done; echo; }
- IFS=:
- set -- A B C
- showargs 1 $*
- showargs 2 "$*"
- showargs 3 $@
- showargs 4 "$@"
-expected-stdout:
- <1> <A> <B> <C>
- <2> <A:B:C>
- <3> <A> <B> <C>
- <4> <A> <B> <C>
----
-
-name: IFS-null-1
-description:
- Simple test, IFS=""
-stdin:
- showargs() { for i; do echo -n " <$i>"; done; echo; }
- IFS=""
- set -- A B C
- showargs 1 $*
- showargs 2 "$*"
- showargs 3 $@
- showargs 4 "$@"
-expected-stdout:
- <1> <A B C>
- <2> <ABC>
- <3> <A B C>
- <4> <A B C>
----
-
-name: IFS-space-colon-1
-description:
- Simple test, IFS=<white-space>:
-stdin:
- showargs() { for i; do echo -n " <$i>"; done; echo; }
- IFS="IFS:"
- set --
- showargs 1 $*
- showargs 2 "$*"
- showargs 3 $@
- showargs 4 "$@"
- showargs 5 : "$@"
-expected-stdout:
- <1>
- <2> <>
- <3>
- <4>
- <5> <:>
----
-
-name: IFS-space-colon-2
-description:
- Simple test, IFS=<white-space>:
- At&t ksh fails this, POSIX says the test is correct.
-stdin:
- showargs() { for i; do echo -n " <$i>"; done; echo; }
- IFS="IFS:"
- set --
- showargs :"$@"
-expected-stdout:
- <:>
----
-
-name: IFS-space-colon-3
-description:
- Simple test, IFS=<white-space>:
- pdksh fails both of these tests
-stdin:
- showargs() { for i; do echo -n " <$i>"; done; echo; }
- IFS="IFS:"
- x=
- set --
- showargs "$x$@"
- showargs "$@$x"
-expected-fail: yes
-expected-stdout:
- <>
- <>
----
-
-name: IFS-space-colon-4
-description:
- Simple test, IFS=<white-space>:
-stdin:
- showargs() { for i; do echo -n " <$i>"; done; echo; }
- IFS="IFS:"
- set --
- showargs "$@$@"
-expected-stdout:
-
----
-
-name: IFS-space-colon-5
-description:
- Simple test, IFS=<white-space>:
- Don't know what POSIX thinks of this. at&t ksh does not do this.
-stdin:
- showargs() { for i; do echo -n " <$i>"; done; echo; }
- IFS="IFS:"
- set --
- showargs "${@:-}"
-expected-stdout:
- <>
----
-
-name: IFS-subst-1
-description:
- Simple test, IFS=<white-space>:
-stdin:
- showargs() { for i; do echo -n " <$i>"; done; echo; }
- IFS="$IFS:"
- x=":b: :"
- echo -n '1:'; for i in $x ; do echo -n " [$i]" ; done ; echo
- echo -n '2:'; for i in :b:: ; do echo -n " [$i]" ; done ; echo
- showargs 3 $x
- showargs 4 :b::
- x="a:b:"
- echo -n '5:'; for i in $x ; do echo -n " [$i]" ; done ; echo
- showargs 6 $x
- x="a::c"
- echo -n '7:'; for i in $x ; do echo -n " [$i]" ; done ; echo
- showargs 8 $x
- echo -n '9:'; for i in ${FOO-`echo -n h:i`th:ere} ; do echo -n " [$i]" ; done ; echo
- showargs 10 ${FOO-`echo -n h:i`th:ere}
- showargs 11 "${FOO-`echo -n h:i`th:ere}"
-expected-stdout:
- 1: [] [b] [] []
- 2: [:b::]
- <3> <> <b> <> <>
- <4> <:b::>
- 5: [a] [b] []
- <6> <a> <b> <>
- 7: [a] [] [c]
- <8> <a> <> <c>
- 9: [h] [ith] [ere]
- <10> <h> <ith> <ere>
- <11> <h:ith:ere>
----
-
diff --git a/bin/pdksh/tests/integer.t b/bin/pdksh/tests/integer.t
deleted file mode 100644
index 7e39612b3ff..00000000000
--- a/bin/pdksh/tests/integer.t
+++ /dev/null
@@ -1,218 +0,0 @@
-name: integer-base-err-1
-description:
- Can't have 0 base (causes shell to exit)
-expected-exit: e != 0
-stdin:
- typeset -i i
- i=3
- i=0#4
- echo $i
-expected-stderr-pattern:
- /^.*:.*0#4.*\n$/
----
-
-name: integer-base-err-2
-description:
- Can't have multiple bases in a `constant' (causes shell to exit)
- (ksh88 fails this test)
-expected-exit: e != 0
-stdin:
- typeset -i i
- i=3
- i=2#110#11
- echo $i
-expected-stderr-pattern:
- /^.*:.*2#110#11.*\n$/
----
-
-name: integer-base-err-3
-description:
- Syntax errors in expressions and effects on bases
- (interactive so errors don't cause exits)
- (ksh88 fails this test - shell exits, even with -i)
-arguments: !-i!
-stdin:
- PS1= # minimize prompt hassles
- typeset -i4 a=10
- typeset -i a=2+
- echo $a
- typeset -i4 a=10
- typeset -i2 a=2+
- echo $a
-expected-stderr-pattern:
- /^([#\$] )?.*:.*2+.*\n.*:.*2+.*\n$/
-expected-stdout:
- 4#22
- 4#22
----
-
-name: integer-base-err-4
-description:
- Are invalid digits (according to base) errors?
- (ksh93 fails this test)
-expected-exit: e != 0
-stdin:
- typeset -i i;
- i=3#4
-expected-stderr-pattern:
- /^([#\$] )?.*:.*3#4.*\n$/
----
-
-
-name: integer-base-1
-description:
- Missing number after base is treated as 0.
-stdin:
- typeset -i i
- i=3
- i=2#
- echo $i
-expected-stdout:
- 0
----
-
-name: integer-base-2
-description:
- Check `stickyness' of base in various situations
-stdin:
- typeset -i i=8
- echo $i
- echo ---------- A
- typeset -i4 j=8
- echo $j
- echo ---------- B
- typeset -i k=8
- typeset -i4 k=8
- echo $k
- echo ---------- C
- typeset -i4 l
- l=3#10
- echo $l
- echo ---------- D
- typeset -i m
- m=3#10
- echo $m
- echo ---------- E
- n=2#11
- typeset -i n
- echo $n
- n=10
- echo $n
- echo ---------- F
- typeset -i8 o=12
- typeset -i4 o
- echo $o
- echo ---------- G
- typeset -i p
- let p=8#12
- echo $p
-expected-stdout:
- 8
- ---------- A
- 4#20
- ---------- B
- 4#20
- ---------- C
- 4#3
- ---------- D
- 3#10
- ---------- E
- 2#11
- 2#1010
- ---------- F
- 4#30
- ---------- G
- 8#12
----
-
-name: integer-base-3
-description:
- More base parsing (hmm doesn't test much..)
-stdin:
- typeset -i aa
- aa=1+12#10+2
- echo $aa
- typeset -i bb
- bb=1+$aa
- echo $bb
- typeset -i bb
- bb=$aa
- echo $bb
- typeset -i cc
- cc=$aa
- echo $cc
-expected-stdout:
- 15
- 16
- 15
- 15
----
-
-name: integer-base-4
-description:
- Check that things not declared as integers are not made integers,
- also, check if base is not reset by -i with no arguments.
- (ksh93 fails - prints 10#20 - go figure)
-stdin:
- xx=20
- let xx=10
- typeset -i | grep '^xx='
- typeset -i4 a=10
- typeset -i a=20
- echo $a
-expected-stdout:
- 4#110
----
-
-name: integer-base-5
-description:
- More base stuff
-stdin:
- typeset -i4 a=3#10
- echo $a
- echo --
- typeset -i j=3
- j=~3
- echo $j
- echo --
- typeset -i k=1
- x[k=k+1]=3
- echo $k
- echo --
- typeset -i l
- for l in 1 2+3 4; do echo $l; done
-expected-stdout:
- 4#3
- --
- -4
- --
- 2
- --
- 1
- 5
- 4
----
-
-name: integer-base-6
-description:
- Even more base stuff
- (ksh93 fails this test - prints 0)
-stdin:
- typeset -i7 i
- i=
- echo $i
-expected-stdout:
- 7#0
----
-
-name: integer-base-7
-description:
- Check that non-integer parameters don't get bases assigned
-stdin:
- echo $(( zz = 8#100 ))
- echo $zz
-expected-stdout:
- 64
- 64
----
-
diff --git a/bin/pdksh/tests/read.t b/bin/pdksh/tests/read.t
deleted file mode 100644
index aced86adc32..00000000000
--- a/bin/pdksh/tests/read.t
+++ /dev/null
@@ -1,56 +0,0 @@
-#
-# To test:
-# POSIX:
-# - if no -r, \ is escape character
-# - \newline disappear
-# - \<IFS> -> don't break here
-# - \<anything-else> -> <anything-else>
-# - if -r, backslash is not special
-# - if stdin is tty and shell interactive
-# - prompt for continuation if \newline (prompt to stderr)
-# - a here-document isn't terminated after newline ????
-# - remaining vars set to empty string (not null)
-# - check field splitting
-# - left over fields and their seperators assigned to last var
-# - exit status is normally 0
-# - exit status is > 0 on eof
-# - exit status > 0 on error
-# - signals interrupt reads
-# extra:
-# - can't change read-only variables
-# - error if var name bogus
-# - set -o allexport effects read
-# ksh:
-# x check default variable: REPLY
-# - check -p, -s, -u options
-# - check var?prompt stuff
-# - "echo a b | read x y" sets x,y in parent shell (at&t)
-#
-name: read-IFS-1
-description:
- Simple test, default IFS
-stdin:
- echo "A B " > IN
- unset x y z
- read x y z < IN
- echo 1: "x[$x] y[$y] z[$z]"
- echo 1a: ${z-z not set}
- read x < IN
- echo 2: "x[$x]"
-expected-stdout:
- 1: x[A] y[B] z[]
- 1a:
- 2: x[A B]
----
-
-name: read-ksh-1
-description:
- If no var specified, REPLY is used
-stdin:
- echo "abc" > IN
- read < IN
- echo "[$REPLY]";
-expected-stdout:
- [abc]
----
-
diff --git a/bin/pdksh/tests/regress.t b/bin/pdksh/tests/regress.t
deleted file mode 100644
index 675ae53497a..00000000000
--- a/bin/pdksh/tests/regress.t
+++ /dev/null
@@ -1,770 +0,0 @@
-#
-# The first 39 of these tests are from the old Bugs script.
-#
-
-name: regression-1
-description:
- Lex array code had problems with this.
-stdin:
- echo foo[
- n=bar
- echo "hi[ $n ]=1"
-expected-stdout:
- foo[
- hi[ bar ]=1
----
-
-
-name: regression-2
-description:
- When PATH is set before running a command, the new path is
- not used in doing the path search
- $ echo echo hi > /tmp/q ; chmod a+rx /tmp/q
- $ PATH=/tmp q
- q: not found
- $
- in comexec() the two lines
- while (*vp != NULL)
- (void) typeset(*vp++, xxx, 0);
- need to be moved out of the switch to before findcom() is
- called - I don't know what this will break.
-stdin:
- : ${PWD:-`pwd 2> /dev/null`}
- : ${PWD:?"PWD not set - can't do test"}
- mkdir Y
- cat > Y/xxxscript << EOF
- #!/bin/sh
- # Need to restore path so echo can be found (some shells don't have
- # it as a built-in)
- PATH=\$OLDPATH
- echo hi
- exit 0
- EOF
- chmod a+rx Y/xxxscript
- export OLDPATH="$PATH"
- PATH=$PWD/Y xxxscript
- exit $?
-expected-stdout:
- hi
----
-
-
-#
-# 3. Sun OS 4.0.x (This seems to be a problem with sun's PENDIN not being done
-# properly)
-# sleep 5^J ls^J ls^J ls [only first ls runs]
-# vi ... ZZ (while waiting type) [some of the input gets eaten]
-# [not present in SunOS 4.1.x]
-#echo " [No automatic test for bug 3 - interactive]"
-
-
-#
-# 4. (fixed)
-#
-#echo " [Don't know what bug 4 was]"
-
-
-#
-# 5. Everywhere
-# File name completion (^X,*) does not mesh well with cd and
-# symbolic links. cd does path simplification wrt $PWD before
-# doing the actual chdir(), while file name completion does
-# not do the simplification. E.g., you are in directory A
-# which has a symbolic link to directory B, you create a file
-# called foobar and you then cd to the symlink to B, and type
-# $ echo ../foo^X
-# and the shell beeps at you. Would be more consistent to
-# do the completion after simplifing the `$PWD/..'.
-#echo " [No automatic test for bug 5 - interactive]"
-
-
-name: regression-6
-description:
- Parsing of $(..) expressions is non-optimal. It is
- impossible to have any parentheses inside the expression.
- I.e.,
- $ ksh -c 'echo $(echo \( )'
- no closing quote
- $ ksh -c 'echo $(echo "(" )'
- no closing quote
- $
- The solution is to hack the parsing clode in lex.c, the
- question is how to hack it: should any parentheses be
- escaped by a backslash, or should recursive parsing be done
- (so quotes could also be used to hide hem). The former is
- easier, the later better...
-stdin:
- echo $(echo \()
-expected-stdout:
- (
----
-
-
-#
-# 7. (fixed)
-#
-#echo " [Don't know what bug 7 was]"
-
-
-#
-# 8. Everywhere - NOT A BUG - this is what at&t ksh88 does
-# Strange typset -x behaviour in functions. The following function
-# does not set the environment variable BLAH outside the function:
-# function blah
-# {
-# typeset -x BLAH=foobar
-# }
-# This function does work:
-# function blah
-# { BLAH=foobar; export BLAH
-# }
-#echo ' [Bug 8 was bogus]'
-
-
-name: regression-9
-description:
- Continue in a for loop does not work right:
- for i in a b c ; do
- if [ $i = b ] ; then
- continue
- fi
- echo $i
- done
- Prints a forever...
-stdin:
- first=yes
- for i in a b c ; do
- if [ $i = b ] ; then
- if [ $first = no ] ; then
- echo 'continue in for loop broken'
- break # hope break isn't broken too :-)
- fi
- first=no
- continue
- fi
- done
- echo bye
-expected-stdout:
- bye
----
-
-
-name: regression-10
-description:
- The following:
- set -- `false`
- echo $?
- shoud not print 0. (according to /bin/sh, at&t ksh88, and the
- getopt(1) man page - not according to POSIX)
-stdin:
- set -- `false`
- echo $?
-expected-stdout:
- 1
----
-
-
-name: regression-11
-description:
- The following:
- x=/foo/bar/blah
- echo ${x##*/}
- should echo blah but on some machines echos /foo/bar/blah.
-stdin:
- x=/foo/bar/blah
- echo ${x##*/}
-expected-stdout:
- blah
----
-
-
-name: regression-12
-description:
- Both of the following echos produce the same output under sh/ksh.att:
- #!/bin/sh
- x="foo bar"
- echo "`echo \"$x\"`"
- echo "`echo "$x"`"
- pdksh produces different output for the former (foo instead of foo\tbar)
-stdin:
- x="foo bar"
- echo "`echo \"$x\"`"
- echo "`echo "$x"`"
-expected-stdout:
- foo bar
- foo bar
----
-
-
-name: regression-13
-description:
- The following command hangs forever:
- $ (: ; cat /etc/termcap) | sleep 2
- This is because the shell forks a shell to run the (..) command
- and this shell has the pipe open. When the sleep dies, the cat
- doesn't get a SIGPIPE 'cause a process (ie, the second shell)
- still has the pipe open.
-
- NOTE: this test provokes a bizarre bug in ksh93 (shell starts reading
- commands from /etc/termcap..)
-time-limit: 10
-stdin:
- echo A line of text that will be duplicated quite a number of times.> t1
- cat t1 t1 t1 t1 t1 t1 t1 t1 t1 t1 t1 t1 t1 t1 t1 t1 > t2
- cat t2 t2 t2 t2 t2 t2 t2 t2 t2 t2 t2 t2 t2 t2 t2 t2 > t1
- cat t1 t1 t1 t1 > t2
- (: ; cat t2) | sleep 1
----
-
-
-name: regression-14
-description:
- The command
- $ (foobar) 2> /dev/null
- generates no output under /bin/sh, but pdksh produces the error
- foobar: not found
- Also, the command
- $ foobar 2> /dev/null
- generates an error under /bin/sh and pdksh, but at&t ksh88 produces
- no error (redirected to /dev/null).
-stdin:
- (you/should/not/see/this/error/1) 2> /dev/null
- you/should/not/see/this/error/2 2> /dev/null
- true
----
-
-
-name: regression-15
-description:
- The command
- $ whence foobar
- generates a blank line under pdksh and sets the exit status to 0.
- at&t ksh88 generates no output and sets the exit status to 1. Also,
- the command
- $ whence foobar cat
- generates no output under at&t ksh88 (pdksh generates a blank line
- and /bin/cat).
-stdin:
- whence does/not/exist > /dev/null
- echo 1: $?
- echo 2: $(whence does/not/exist | wc -l)
- echo 3: $(whence does/not/exist cat | wc -l)
-expected-stdout:
- 1: 1
- 2: 0
- 3: 0
----
-
-
-name: regression-16
-description:
- ${var%%expr} seems to be broken in many places. On the mips
- the commands
- $ read line < /etc/passwd
- $ echo $line
- root:0:1:...
- $ echo ${line%%:*}
- root
- $ echo $line
- root
- $
- change the value of line. On sun4s & pas, the echo ${line%%:*} doesn't
- work. Haven't checked elsewhere...
-script:
- read x
- y=$x
- echo ${x%%:*}
- echo $x
-stdin:
- root:asdjhasdasjhs:0:1:Root:/:/bin/sh
-expected-stdout:
- root
- root:asdjhasdasjhs:0:1:Root:/:/bin/sh
----
-
-
-name: regression-17
-description:
- The command
- . /foo/bar
- should set the exit status to non-zero (sh and at&t ksh88 do).
- XXX doting a non existant file is a fatal error for a script
-stdin:
- . does/not/exist
-expected-exit: e != 0
-expected-stderr-pattern: /.?/
----
-
-
-#
-# 18. Everywhere
-# In vi mode ^X (and *) can dump core:
-# $ ab[cd^XMemory fault (core dumped)
-#echo " [No automatic test for bug 18 - interactive]"
-
-
-name: regression-19
-description:
- Both of the following echos should produce the same thing, but don't:
- $ x=foo/bar
- $ echo ${x%/*}
- foo
- $ echo "${x%/*}"
- foo/bar
-stdin:
- x=foo/bar
- echo "${x%/*}"
-expected-stdout:
- foo
----
-
-
-#
-# 20. (same as 18)
-#
-
-
-name: regression-21
-description:
- backslash does not work as expected in case labels:
- $ x='-x'
- $ case $x in
- -\?) echo hi
- esac
- hi
- $ x='-?'
- $ case $x in
- -\\?) echo hi
- esac
- hi
- $
-stdin:
- case -x in
- -\?) echo fail
- esac
----
-
-
-name: regression-22
-description:
- Quoting backquotes inside backquotes doesn't work:
- $ echo `echo hi \`echo there\` folks`
- asks for more info. sh and at&t ksh88 both echo
- hi there folks
-stdin:
- echo `echo hi \`echo there\` folks`
-expected-stdout:
- hi there folks
----
-
-
-name: regression-23
-description:
- )) is not treated `correctly':
- $ (echo hi ; (echo there ; echo folks))
- missing ((
- $
- instead of (as sh and ksh.att)
- $ (echo hi ; (echo there ; echo folks))
- hi
- there
- folks
- $
-stdin:
- ( : ; ( : ; echo hi))
-expected-stdout:
- hi
----
-
-
-#
-# 24. strangeness with file name completion involving symlinks to nowhere
-# $ mkdir foo foo/bar
-# $ ln -s /stuff/junk foo/bar/xx
-# $ echo foo/*/xx 
-# (beep)
-# $
-#echo " [No automatic test for bug 24 - interactive]"
-
-
-name: regression-25
-description:
- Check reading stdin in a while loop. The read should only read
- a single line, not a whole stdio buffer; the cat should get
- the rest.
-stdin:
- (echo a; echo b) | while read x ; do
- echo $x
- cat > /dev/null
- done
-expected-stdout:
- a
----
-
-
-name: regression-26
-description:
- Check reading stdin in a while loop. The read should read both
- lines, not just the first.
-script:
- a=
- while [ "$a" != xxx ] ; do
- last=$x
- read x
- /bin/cat /dev/null | sed 's/x/y/'
- a=x$a
- done
- echo $last
-stdin:
- a
- b
-expected-stdout:
- b
----
-
-
-name: regression-27
-description:
- The command
- . /does/not/exist
- should cause a script to exit.
-stdin:
- . does/not/exist
- echo hi
-expected-exit: e != 0
-expected-stderr-pattern: /does\/not\/exist/
----
-
-
-name: regression-28
-description:
- variable assignements not detected well
-stdin:
- a.x=1 echo hi
-expected-exit: e != 0
-expected-stderr-pattern: /a\.x=1/
----
-
-
-name: regression-29
-description:
- alias expansion different from at&t ksh88
-stdin:
- alias a='for ' b='i in'
- a b hi ; do echo $i ; done
-expected-stdout:
- hi
----
-
-
-name: regression-30
-description:
- strange characters allowed inside ${...}
-stdin:
- echo ${a{b}}
-expected-exit: e != 0
-expected-stderr-pattern: /.?/
----
-
-
-name: regression-31
-description:
- Does read handle partial lines correctly
-script:
- a= ret=
- while [ "$a" != xxx ] ; do
- read x y z
- ret=$?
- a=x$a
- done
- echo "[$x]"
- echo $ret
-stdin: !
- a A aA
- b B Bb
- c
-expected-stdout:
- [c]
- 1
----
-
-
-name: regression-32
-description:
- Does read set variables to null at eof?
-script:
- a=
- while [ "$a" != xxx ] ; do
- read x y z
- a=x$a
- done
- echo 1: ${x-x not set} ${y-y not set} ${z-z not set}
- echo 2: ${x:+x not null} ${y:+y not null} ${z:+z not null}
-stdin:
- a A Aa
- b B Bb
-expected-stdout:
- 1:
- 2:
----
-
-
-name: regression-33
-description:
- Does umask print a leading 0 when umask is 3 digits?
-stdin:
- umask 222
- umask
-expected-stdout:
- 0222
----
-
-
-#
-#
-# Does umask print a umask of 0 sanely?
-# There is lots of variety here (0, 00, 000, and 0000 have all been
-# seen in various shells...)
-#
-#echo ' [Bug 34 was bogus]'
-
-
-name: regression-35
-description:
- Tempory files used for here-docs in functions get trashed after
- the function is parsed (before it is executed)
-stdin:
- f1() {
- cat <<- EOF
- F1
- EOF
- f2() {
- cat <<- EOF
- F2
- EOF
- }
- }
- f1
- f2
- unset -f f1
- f2
-expected-stdout:
- F1
- F2
- F2
----
-
-
-name: regression-36
-description:
- Command substitution breaks reading in while loop
- (test from <sjg@void.zen.oz.au>)
-stdin:
- (echo abcdef; echo; echo 123) |
- while read line
- do
- # the following line breaks it
- c=`echo $line | wc -c`
- echo $c
- done
-expected-stdout:
- 7
- 1
- 4
----
-
-
-name: regression-37
-description:
- Machines with broken times() (reported by <sjg@void.zen.oz.au>)
- time does not report correct real time
-stdin:
- time sleep 1
-expected-stderr-pattern: !/^\s*0\.0[\s\d]+real|^\s*real[\s]+0+\.0/
----
-
-
-name: regression-38
-description:
- set -e doesn't ignore exit codes for if/while/until/&&/||/!.
-arguments: !-e!
-stdin:
- if false; then echo hi ; fi
- false || true
- false && true
- while false; do echo hi; done
- echo ok
-expected-stdout:
- ok
----
-
-
-name: regression-39
-description:
- set -e: errors in command substitutions aren't ignored
- Not clear if they should be or not...
-expected-fail: yes
-arguments: !-e!
-stdin:
- echo `false; echo hi`
-expected-stdout:
- hi
----
-
-name: regression-40
-description:
- This used to cause a core dump
-env-setup: !RANDOM=12!
-stdin:
- echo hi
-expected-stdout:
- hi
----
-
-name: regression-41
-description:
- foo should be set to bar (should not be empty)
-stdin:
- foo=`
- echo bar`
- echo "($foo)"
-expected-stdout:
- (bar)
----
-
-name: regression-42
-description:
- Can't use command line assignments to assign readonly parameters.
-stdin:
- foo=bar
- readonly foo
- foo=stuff env | grep '^foo'
-expected-exit: e != 0
-expected-stderr-pattern:
- /.*read *only.*/
----
-
-name: regression-43
-description:
- Can subshells be prefixed by redirections (historical shells allow
- this)
-stdin:
- < /dev/null (sed 's/^/X/')
----
-
-name: regression-44
-description:
- getopts sets OPTIND correctly for unparsed option
-stdin:
- set -- -a -a -x
- while getopts :a optc; do
- echo "OPTARG=$OPTARG, OPTIND=$OPTIND, optc=$optc."
- done
- echo done
-expected-stdout:
- OPTARG=, OPTIND=2, optc=a.
- OPTARG=, OPTIND=3, optc=a.
- OPTARG=x, OPTIND=3, optc=?.
- done
----
-
-name: regression-45
-description:
- Parameter assignments with [] recognized correctly
-stdin:
- FOO=*[12]
- BAR=abc[
- MORE=[abc]
- JUNK=a[bc
- echo "<$FOO>"
- echo "<$BAR>"
- echo "<$MORE>"
- echo "<$JUNK>"
-expected-stdout:
- <*[12]>
- <abc[>
- <[abc]>
- <a[bc>
----
-
-name: regression-46
-description:
- Check that alias expansion works in command substitutions and
- at the end of file.
-stdin:
- alias x='echo hi'
- FOO="`x` "
- echo "[$FOO]"
- x
-expected-stdout:
- [hi ]
- hi
----
-
-name: regression-47
-description:
- Check that aliases are fully read.
-stdin:
- alias x='echo hi;
- echo there'
- x
- echo done
-expected-stdout:
- hi
- there
- done
----
-
-name: regression-48
-description:
- Check that (here doc) temp files are not left behind after an exec.
-stdin:
- mkdir foo || exit 1
- TMPDIR=$PWD/foo $0 <<- 'EOF'
- x() {
- sed 's/^/X /' << E_O_F
- hi
- there
- folks
- E_O_F
- echo "done ($?)"
- }
- exec /bin/echo subtest-1 hi
- EOF
- echo subtest-1 foo/*
- TMPDIR=$PWD/foo $0 <<- 'EOF'
- sed 's/^/X /' << E_O_F; exec /bin/echo subtest-2 hi
- a
- few
- lines
- E_O_F
- EOF
- echo subtest-2 foo/*
-expected-stdout:
- subtest-1 hi
- subtest-1 foo/*
- X a
- X few
- X lines
- subtest-2 hi
- subtest-2 foo/*
----
-
-name: regression-49
-description:
- Check that unset params with attributes are reported by set, those
- sans attributes are not.
-stdin:
- unset FOO BAR
- echo X$FOO
- export BAR
- typeset -i BLAH
- set | grep FOO
- set | grep BAR
- set | grep BLAH
-expected-stdout:
- X
- BAR
- BLAH
----
-
diff --git a/bin/pdksh/tests/th b/bin/pdksh/tests/th
deleted file mode 100644
index ebe54718ece..00000000000
--- a/bin/pdksh/tests/th
+++ /dev/null
@@ -1,819 +0,0 @@
-#!/usr/bin/perl
-
-#
-# Test harness for pdksh tests.
-#
-# Example test:
-# name: a-test
-# description:
-# a test to show how tests are done
-# arguments: !-x!-f!
-# stdin:
-# echo -n *
-# false
-# expected-stdout: !
-# *
-# expected-stderr:
-# + echo -n *
-# + false
-# expected-exit: 1
-# ---
-# This runs the test-program (eg, pdksh) with the arguments -x and -f,
-# standard input is a file containing "echo hi*\nfalse\n". The program
-# is expected to produce "hi*" (no trailing newline) on standard output,
-# "+ echo hi*\n+false\n" on standard error, and an exit code of 1.
-#
-#
-# Format of test files:
-# - blank lines and lines starting with # are ignored
-# - a test file contains a series of tests
-# - a test is a series of tag:value pairs ended with a "---" line
-# (leading/trailing spaces are stripped from the first line of value)
-# - test tags are:
-# Tag Flag Description
-# ----- ---- -----------
-# name r The name of the test; should be unique
-# description m What test does
-# arguments M Arguments to pass to the program;
-# default is no arguments.
-# script m Value is written to a file which
-# is passed as an argument to the program
-# (after the arguments arguments)
-# stdin m Value is written to a file which is
-# used as standard-input for the program;
-# default is to use /dev/null.
-# perl-setup m Value is a perl script which is executed
-# just before the test is run. Try to
-# avoid using this...
-# perl-cleanup m Value is a perl script which is executed
-# just after the test is run. Try to
-# avoid using this...
-# env-setup M Value is a list of NAME=VALUE elements
-# which are put in the environment before
-# the test is run. If the =VALUE is
-# missing, NAME is removed from the
-# environment. Programs are run with
-# the following minimal environment:
-# USER, LOGNAME, HOME, PATH, SHELL
-# (values taken from the environment of
-# the test harness).
-# time-limit Time limit - the program is sent a
-# SIGKILL N seconds. Default is no
-# limit.
-# expected-fail `yes' if the test is expected to fail.
-# expected-exit expected exit code. Can be a number,
-# or a C expression using the variables
-# e, s and w (exit code, termination
-# signal, and status code).
-# expected-stdout m What the test should generate on stdout;
-# default is to expect no output.
-# expected-stdout-pattern m A perl pattern which matches the
-# expected output.
-# expected-stderr m What the test should generate on stderr;
-# default is to expect no output.
-# expected-stderr-pattern m A perl pattern which matches the
-# expected standard error.
-# Flag meanings:
-# r tag is required (eg, a test must have a name tag).
-# m value can be multiple lines. Lines must be prefixed with
-# a tab. If the value part of the initial tag:value line is
-# - empty: the initial blank line is stripped.
-# - a lone !: the last newline in the value is stripped;
-# M value can be multiple lines (prefixed by a tab) and consists
-# of multiple fields, delimited by a field seperator character.
-# The value must start and end with the f-s-c.
-#
-
-require 'signal.ph';
-require 'errno.ph';
-require 'getopts.pl';
-
-($prog = $0) =~ s#.*/##;
-
-$Usage = <<EOF ;
-Usage: $prog [-s test-set] [-p prog] [-v] test-name ...
- -p p Use p as the program to test
- -s s Read tests from file s; if s is a directory, it is recursively
- scaned for test files (which end in .t).
- -t t Use t as default time limit for tests (default is unlimited)
- -v Verbose mode: print reason test failed.
- test-name(s) specifies the name of the test(s) to run; if none are
- specified, all tests are run.
-EOF
-
-#
-# r - required
-# m - can be multi-line
-# M - multi-line, but without trailing newline
-#
-%test_fields = (
- 'name', 'r',
- 'description', 'm',
- 'arguments', 'M',
- 'script', 'm',
- 'stdin', 'm',
- 'perl-setup', 'm',
- 'perl-cleanup', 'm',
- 'env-setup', 'M',
- 'time-limit', '',
- 'expected-fail', '',
- 'expected-exit', '',
- 'expected-stdout', 'm',
- 'expected-stdout-pattern', 'm',
- 'expected-stderr', 'm',
- 'expected-stderr-pattern', 'm',
- );
-# Filled in by read_test()
-%internal_test_fields = (
- ':full-name', 1, # file:name
- ':long-name', 1, # dir/file:lineno:name
- );
-
-$temps = "/tmp/rts$$";
-$tempi = "/tmp/rti$$";
-$tempo = "/tmp/rto$$";
-$tempe = "/tmp/rte$$";
-$tempdir = "/tmp/rtd$$";
-
-$nfailed = 0;
-$nxfailed = 0;
-$npassed = 0;
-$nxpassed = 0;
-
-%known_tests = ();
-
-if (!&Getopts('p:s:t:v')) {
- print STDERR $Usage;
- exit 1;
-}
-
-die "$prog: no program specified (use -p)\n" if !defined $opt_p;
-die "$prog: no test set specified (use -s)\n" if !defined $opt_s;
-$test_prog = $opt_p;
-$verbose = defined $opt_v && $opt_v;
-$test_set = $opt_s;
-if (defined $opt_t) {
- die "$prog: bad -t argument (should be number > 0): $opt_t\n"
- if $opt_t !~ /^\d+$/ || $opt_t <= 0;
- $default_time_limit = $opt_t;
-}
-
-# Note which tests are to be run.
-%do_test = ();
-grep($do_test{$_} = 1, @ARGV);
-$all_tests = @ARGV == 0;
-
-# Set up a very minimal environment
-%new_env = ();
-foreach $env (('USER', 'LOGNAME', 'HOME', 'PATH', 'SHELL')) {
- $new_env{$env} = $ENV{$env} if defined $ENV{$env};
-}
-%old_env = %ENV;
-
-# The following doesn't work with perl5... Need to do it explicitly - yuck.
-#%ENV = %new_env;
-foreach $k (keys(%ENV)) {
- delete $ENV{$k};
-}
-$ENV{$k} = $v while ($k,$v) = each %new_env;
-
-die "$prog: couldn't make directory $tempdir - $!\n" if !mkdir($tempdir, 0777);
-
-chop($pwd = `pwd 2> /dev/null`);
-die "$prog: couldn't get current working directory\n" if $pwd eq '';
-die "$prog: couldn't cd to $pwd - $!\n" if !chdir($pwd);
-
-$test_prog = "$pwd/$test_prog" if substr($test_prog, 0, 1) ne '/';
-die "$prog: $test_prog is not executable - bye\n" if ! -x $test_prog;
-
-@trap_sigs = ('TERM', 'QUIT', 'INT', 'PIPE', 'HUP');
-@SIG{@trap_sigs} = ('cleanup_exit') x @trap_sigs;
-$child_kill_ok = 0;
-$SIG{'ALRM'} = 'catch_sigalrm';
-
-$| = 1;
-
-if (-d $test_set) {
- $file_prefix_skip = length($test_set) + 1;
- $ret = &process_test_dir($test_set);
-} else {
- $file_prefix_skip = 0;
- $ret = &process_test_file($test_set);
-}
-&cleanup_exit() if !defined $ret;
-
-$tot_failed = $nfailed + $nxfailed;
-$tot_passed = $npassed + $nxpassed;
-if ($tot_failed || $tot_passed) {
- print "Total failed: $tot_failed";
- print " ($nxfailed unexpected)" if $nxfailed;
- print " (as expected)" if $nfailed && !$nxfailed;
- print "\nTotal passed: $tot_passed";
- print " ($nxpassed unexpected)" if $nxpassed;
- print "\n";
-}
-
-&cleanup_exit('ok');
-
-sub
-cleanup_exit
-{
- local($sig, $exitcode) = ('', 1);
-
- if ($_[0] eq 'ok') {
- $exitcode = 0;
- } elsif ($_[0] ne '') {
- $sig = $_[0];
- }
-
- unlink($tempi, $tempo, $tempe, $temps);
- &scrub_dir($tempdir) if defined $tempdir;
- rmdir($tempdir) if defined $tempdir;
-
- if ($sig) {
- $SIG{$sig} = 'DEFAULT';
- kill $sig, $$;
- return;
- }
- exit $exitcode;
-}
-
-sub
-catch_sigalrm
-{
- $SIG{'ALRM'} = 'catch_sigalrm';
- kill(9, $child_pid) if $child_kill_ok;
- $child_killed = 1;
-}
-
-sub
-process_test_dir
-{
- local($dir) = @_;
- local($ret, $file);
- local(@todo) = ();
-
- if (!opendir(DIR, $dir)) {
- print STDERR "$prog: can't open directory $dir - $!\n";
- return undef;
- }
- while ($file = readdir(DIR)) {
- push(@todo, $file) if $file =~ /^[^.].*\.t$/;
- }
- closedir(DIR);
-
- foreach $file (@todo) {
- $file = "$dir/$file";
- if (-d $file) {
- $ret = &process_test_dir($file);
- } elsif (-f _) {
- $ret = &process_test_file($file);
- }
- last if !defined $ret;
- }
-
- return $ret;
-}
-
-sub
-process_test_file
-{
- local($file) = @_;
- local($ret);
-
- if (!open(IN, $file)) {
- die "$prog: can't open $file - $!\n";
- return undef;
- }
- while (1) {
- $ret = &read_test($file, IN, *test);
- last if !defined $ret || !$ret;
- next if !$all_tests && !$do_test{$test{'name'}};
- $ret = &run_test(*test);
- last if !defined $ret;
- }
- close(IN);
-
- return $ret;
-}
-
-sub
-run_test
-{
- local(*test) = @_;
- local($name) = $test{':full-name'};
-
- #print "Running test $name...\n" if $verbose;
-
- if (defined $test{'stdin'}) {
- return undef if !&write_file($tempi, $test{'stdin'});
- $ifile = $tempi;
- } else {
- $ifile = '/dev/null';
- }
-
- if (defined $test{'script'}) {
- return undef if !&write_file($temps, $test{'script'});
- }
-
- return undef if !&scrub_dir($tempdir);
-
- if (!chdir($tempdir)) {
- print STDERR "$prog: couldn't cd to $tempdir - $!\n";
- return undef;
- }
-
- if (defined $test{'perl-setup'}) {
- eval $test{'perl-setup'};
- if ($@ ne '') {
- print STDERR "$prog:$test{':long-name'}: error running perl-setup - $@\n";
- return undef;
- }
- }
-
- $pid = fork;
- if (!defined $pid) {
- print STDERR "$prog: can't fork - $!\n";
- return undef;
- }
- if (!$pid) {
- @SIG{@trap_sigs} = ('DEFAULT') x @trap_sigs;
- $SIG{'ALRM'} = 'DEFAULT';
- if (defined $test{'env-setup'}) {
- local($var, $val, $i);
-
- foreach $var (split(substr($test{'env-setup'}, 0, 1),
- $test{'env-setup'}))
- {
- $i = index($var, '=');
- next if $i == 0 || $var eq '';
- if ($i < 0) {
- delete $ENV{$var};
- } else {
- $ENV{substr($var, 0, $i)} = substr($var, $i + 1);
- }
- }
- }
- if (!open(STDIN, "< $ifile")) {
- print STDERR "$prog: couldn't open $ifile in child - $!\n";
- kill('TERM', $$);
- }
- if (!open(STDOUT, "> $tempo")) {
- print STDERR "$prog: couldn't open $tempo in child - $!\n";
- kill('TERM', $$);
- }
- if (!open(STDERR, "> $tempe")) {
- print STDOUT "$prog: couldn't open $tempe in child - $!\n";
- kill('TERM', $$);
- }
- @argv = ($test_prog);
- if (defined $test{'arguments'}) {
- push(@argv,
- split(substr($test{'arguments'}, 0, 1),
- substr($test{'arguments'}, 1)));
- }
- push(@argv, $temps) if defined $test{'script'};
- exec(@argv);
- print STDERR "$prog: couldn't execute $test_prog - $!\n";
- kill('TERM', $$);
- exit(95);
- }
- $child_pid = $pid;
- $child_killed = 0;
- $child_kill_ok = 1;
- alarm($test{'time-limit'}) if defined $test{'time-limit'};
- while (1) {
- $xpid = waitpid($pid, 0);
- $child_kill_ok = 0;
- if ($xpid < 0) {
- next if $! == &EINTR;
- print STDERR "$prog: error waiting for child - $!\n";
- return undef;
- }
- last;
- }
- $status = $?;
- alarm(0) if defined $test{'time-limit'};
-
- $failed = 0;
- $why = '';
-
- if ($child_killed) {
- $failed = 1;
- $why .= "\ttest timed out (limit of $test{'time-limit'} seconds)\n";
- }
-
- $ret = &eval_exit($test{'long-name'}, $status, $test{'expected-exit'});
- return undef if !defined $ret;
- if (!$ret) {
- local($expl);
-
- $failed = 1;
- if (($status & 0xff) == 0x7f) {
- $expl = "stopped";
- } elsif (($status & 0xff)) {
- $expl = "signal " . ($status & 0x7f);
- } else {
- $expl = "exit-code " . (($status >> 8) & 0xff);
- }
- $why .=
- "\tunexpected exit status $status ($expl), expected $test{'expected-exit'}\n";
- }
-
- $tmp = &check_output($test{'long-name'}, $tempo, 'stdout',
- $test{'expected-stdout'}, $test{'expected-stdout-pattern'});
- return undef if !defined $tmp;
- if ($tmp ne '') {
- $failed = 1;
- $why .= $tmp;
- }
-
- $tmp = &check_output($test{'long-name'}, $tempe, 'stderr',
- $test{'expected-stderr'}, $test{'expected-stderr-pattern'});
- return undef if !defined $tmp;
- if ($tmp ne '') {
- $failed = 1;
- $why .= $tmp;
- }
-
- if (defined $test{'perl-cleanup'}) {
- eval $test{'perl-cleanup'};
- if ($@ ne '') {
- print STDERR "$prog:$test{':long-name'}: error running perl-cleanup - $@\n";
- return undef;
- }
- }
-
- if (!chdir($pwd)) {
- print STDERR "$prog: couldn't cd to $pwd - $!\n";
- return undef;
- }
-
- if ($failed) {
- if (!$test{'expected-fail'}) {
- print "FAIL $name\n";
- $nxfailed++;
- } else {
- print "fail $name (as expected)\n";
- $nfailed++;
- }
- $why = "\tDescription"
- . &wrap_lines($test{'description'}, " (missing)\n")
- . $why;
- } elsif ($test{'expected-fail'}) {
- print "PASS $name (unexpectedly)\n";
- $nxpassed++;
- } else {
- print "pass $name\n";
- $npassed++;
- }
- print $why if $verbose;
- return 0;
-}
-
-sub
-scrub_dir
-{
- local($dir) = @_;
- local(@todo) = ();
- local($file);
-
- if (!opendir(DIR, $dir)) {
- print STDERR "$prog: couldn't open direcotry $dir - $!\n";
- return undef;
- }
- while ($file = readdir(DIR)) {
- push(@todo, $file) if $file ne '.' && $file ne '..';
- }
- closedir(DIR);
- foreach $file (@todo) {
- $file = "$dir/$file";
- if (-d $file) {
- return undef if !&scrub_dir($file);
- if (!rmdir($file)) {
- print STDERR "$prog: couldn't rmdir $file - $!\n";
- return undef;
- }
- } else {
- if (!unlink($file)) {
- print STDERR "$prog: couldn't unlink $file - $!\n";
- return undef;
- }
- }
- }
- return 1;
-}
-
-sub
-write_file
-{
- local($file, $str) = @_;
-
- if (!open(TEMP, "> $file")) {
- print STDERR "$prog: can't open $file - $!\n";
- return undef;
- }
- print TEMP $str;
- if (!close(TEMP)) {
- print STDERR "$prog: error writing $file - $!\n";
- return undef;
- }
- return 1;
-}
-
-sub
-check_output
-{
- local($name, $file, $what, $expect, $expect_pat) = @_;
- local($got) = '';
- local($why) = '';
- local($ret);
-
- if (!open(TEMP, "< $file")) {
- print STDERR "$prog:$name($what): couldn't open $file after running program - $!\n";
- return undef;
- }
- while (<TEMP>) {
- $got .= $_;
- }
- close(TEMP);
- if (defined $expect_pat) {
- $_ = $got;
- $ret = eval "$expect_pat";
- if ($@ ne '') {
- print STDERR "$prog:$name($what): error evaluating $what pattern: $expect_pat - $@\n";
- return undef;
- }
- if (!$ret) {
- $why = "\tunexpected $what - wanted pattern";
- $why .= &wrap_lines($expect_pat);
- $why .= "\tgot";
- $why .= &wrap_lines($got);
- }
- } else {
- $expect = '' if !defined $expect;
- if ($got ne $expect) {
- $why .= "\tunexpected $what - " . &first_diff($expect, $got) . "\n";
- $why .= "\twanted";
- $why .= &wrap_lines($expect);
- $why .= "\tgot";
- $why .= &wrap_lines($got);
- }
- }
- return $why;
-}
-
-sub
-wrap_lines
-{
- local($str, $empty) = @_;
- local($nonl) = substr($str, -1, 1) ne "\n";
-
- return (defined $empty ? $empty : " nothing\n") if $str eq '';
- substr($str, 0, 0) = ":\n";
- $str =~ s/\n/\n\t\t/g;
- if ($nonl) {
- $str .= "\n\t[incomplete last line]\n";
- } else {
- chop($str);
- chop($str);
- }
- return $str;
-}
-
-sub
-first_diff
-{
- local($exp, $got) = @_;
- local($lineno, $char) = (1, 1);
- local($i, $len);
- local($ce, $cg);
-
- $len = length($exp);
- if ($len != length($got)) {
- if ($len < length($got)) {
- if (substr($got, 0, $len) eq $exp) {
- return "got too much output";
- }
- } elsif (substr($exp, 0, $len) eq $got) {
- return "got too little output";
- }
- $len = length($got);
- }
- for ($i = 0; $i < $len; $i++) {
- $ce = substr($exp, $i, 1);
- $cg = substr($got, $i, 1);
- last if $ce ne $cg;
- $char++;
- if ($ce eq "\n") {
- $lineno++;
- $char = 1;
- }
- }
- return "first difference: line $lineno, char $char"
-}
-
-sub
-eval_exit
-{
- local($name, $status, $expect) = @_;
- local($expr);
- local($w, $e, $s) = ($status, ($status >> 8) & 0xff, $status & 0x7f);
-
- $e = -1000 if $status & 0xff;
- $s = -1000 if $s == 0x7f;
- if (!defined $expect) {
- $expr = '$w == 0';
- } elsif ($expect =~ /^(|-)\d+$/) {
- $expr = "\$e == $expect";
- } else {
- $expr = $expect;
- $expr =~ s/\b([wse])\b/\$$1/g;
- $expr =~ s/\b(SIG[A-Z0-9]+)\b/&$1/g;
- }
- $w = eval $expr;
- if ($@ ne '') {
- print STDERR "$prog:$test{':long-name'}: bad expected-exit expression: $expect ($@)\n";
- return undef;
- }
- return $w;
-}
-
-sub
-read_test
-{
- local($file, $in, *test) = @_;
- local($field, $val, $flags, $do_chop, $need_redo, $start_lineno);
-
- %test = ();
- while (<$in>) {
- next if /^\s*$/;
- next if /^ *#/;
- last if /^\s*---\s*$/;
- $start_lineno = $. if !defined $start_lineno;
- if (!/^([-\w]+):\s*(|\S|\S.*\S)\s*$/) {
- print STDERR "$prog:$file:$.: unrecognized line\n";
- return undef;
- }
- ($field, $val) = ($1, $2);
- if (defined $test{$field}) {
- print STDERR "$prog:$file:$.: multiple \"$field\" fields\n";
- return undef;
- }
- $flags = $test_fields{$field};
- if (!defined $flags) {
- print STDERR "$prog:$file:$.: unrecognized field \"$field\"\n";
- return undef;
- }
- $do_chop = $flags !~ /m/;
- $need_redo = 0;
- if ($val eq '' || $val eq '!') {
- if ($flags =~ /[Mm]/) {
- $do_chop = 1 if $val eq '!';
- $val = '';
- while (<$in>) {
- last if !/^\t/;
- $val .= $';
- }
- chop $val if $do_chop;
- $do_chop = 1;
- $need_redo = 1;
- } elsif ($val eq '') {
- print STDERR
- "$prog:$file:$.: no value given for field \"$field\"\n";
- return undef;
- }
- }
- $val .= "\n" if !$do_chop;
- $test{$field} = $val;
- redo if $need_redo;
- }
- if ($_ eq '') {
- if (%test) {
- print STDERR
- "$prog:$file:$start_lineno: end-of-file while reading test\n";
- return undef;
- }
- return 0;
- }
-
- while (($field, $val) = each %test_fields) {
- if ($val =~ /r/ && !defined $test{$field}) {
- print STDERR
- "$prog:$file:$start_lineno: required field \"$field\" missing\n";
- return undef;
- }
- }
-
- $test{':full-name'} = substr($file, $file_prefix_skip) . ":$test{'name'}";
- $test{':long-name'} = "$file:$start_lineno:$test{'name'}";
-
- # Syntax check on specific fields
- if (defined $test{'expected-fail'}) {
- if ($test{'expected-fail'} !~ /^(yes|no)$/) {
- print STDERR
- "$prog:$test{':long-name'}: bad value for expected-fail field\n";
- return undef;
- }
- $test{'expected-fail'} = $1 eq 'yes';
- } else {
- $test{'expected-fail'} = 0;
- }
- if (defined $test{'arguments'}) {
- local($firstc) = substr($test{'arguments'}, 0, 1);
-
- if (substr($test{'arguments'}, -1, 1) ne $firstc) {
- print STDERR "$prog:$test{':long-name'}: arguments field doesn't start and end with the same character\n";
- return undef;
- }
- }
- if (defined $test{'env-setup'}) {
- local($firstc) = substr($test{'env-setup'}, 0, 1);
-
- if (substr($test{'env-setup'}, -1, 1) ne $firstc) {
- print STDERR "$prog:$test{':long-name'}: env-setup field doesn't start and end with the same character\n";
- return undef;
- }
- }
- if (defined $test{'expected-exit'}) {
- local($val) = $test{'expected-exit'};
-
- if ($val =~ /^(|-)\d+$/) {
- if ($val < 0 || $val > 255) {
- print STDERR "$prog:$test{':long-name'}: expected-exit value $val not in 0..255\n";
- return undef;
- }
- } elsif ($val !~ /^([\s<>+-=*%\/&|!()]|\b[wse]\b|\bSIG[A-Z0-9]+\b)+$/) {
- print STDERR "$prog:$test{':long-name'}: bad expected-exit expression: $val\n";
- return undef;
- }
- } else {
- $test{'expected-exit'} = 0;
- }
- if (defined $test{'expected-stdout'}
- && defined $test{'expected-stdout-pattern'})
- {
- print STDERR "$prog:$test{':long-name'}: can't use both expected-stdout and expected-stdout-pattern\n";
- return undef;
- }
- if (defined $test{'expected-stderr'}
- && defined $test{'expected-stderr-pattern'})
- {
- print STDERR "$prog:$test{':long-name'}: can't use both expected-stderr and expected-stderr-pattern\n";
- return undef;
- }
- if (defined $test{'time-limit'}) {
- if ($test{'time-limit'} !~ /^\d+$/ || $test{'time-limit'} == 0) {
- print STDERR
- "$prog:$test{':long-name'}: bad value for time-limit field\n";
- return undef;
- }
- } elsif (defined $default_time_limit) {
- $test{'time-limit'} = $default_time_limit;
- }
-
- if (defined $known_tests{$test{'name'}}) {
- print STDERR "$prog:$test{':long-name'}: warning: duplicate test name ${test{'name'}}\n";
- }
- $known_tests{$test{'name'}} = 1;
-
- return 1;
-}
-
-sub
-touch
-{
- local(@files) = @_;
- local($file);
-
- foreach $file (@files) {
- if (!open(T, "> $file")) {
- die "Couldn't touch $file\n";
- }
- close(T);
- }
- return 1;
-}
-
-sub
-tty_msg
-{
- local($msg) = @_;
-
- open(TTY, "> /dev/tty") || return 0;
- print TTY $msg;
- close(TTY);
- return 1;
-}
-
-sub
-never_called_funcs
-{
- return 0;
- &tty_msg("hi\n");
- &touch("/tmp/foo");
- &never_called_funcs();
- &catch_sigalrm();
- $old_env{'foo'} = 'bar';
- $internal_test_fields{'foo'} = 'bar';
-}
diff --git a/bin/pdksh/tests/th.sh b/bin/pdksh/tests/th.sh
deleted file mode 100644
index 3ca78e8c955..00000000000
--- a/bin/pdksh/tests/th.sh
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/bin/sh
-
-#
-# Simple script to find perl and run it
-#
-
-# Avoid common problems with ENV (though perl shouldn't let it through)
-# (can you believe some shells don't have an unset???)
-unset ENV
-
-x=x
-[ -x /bin/sh ] 2> /dev/null || x=f
-
-IFS=:$IFS
-perl=
-for i in $PATH; do
- [ X"$i" = X ] && i=.
- for j in perl perl4 perl5 ; do
- [ -$x "$i/$j" ] && perl=$i/$j && break 2
- done
-done
-
-[ X"$perl" = X ] && {
- echo "$0: can't find perl - bye\n" 1>&2
- exit 1
- }
-
-exec $perl "$@"
diff --git a/bin/pdksh/tests/unclass1.t b/bin/pdksh/tests/unclass1.t
deleted file mode 100644
index 55d4e58976f..00000000000
--- a/bin/pdksh/tests/unclass1.t
+++ /dev/null
@@ -1,97 +0,0 @@
-name: xxx-quoted-newline-1
-description:
- Check that \<newline> works inside of ${}
-stdin:
- abc=2
- echo ${ab\
- c}
-expected-stdout:
- 2
----
-
-name: xxx-quoted-newline-2
-description:
- Check that \<newline> works at the start of a here document
-stdin:
- cat << EO\
- F
- hi
- EOF
-expected-stdout:
- hi
----
-
-name: xxx-quoted-newline-3
-description:
- Check that \<newline> works at the end of a here document
-stdin:
- cat << EOF
- hi
- EO\
- F
-expected-stdout:
- hi
----
-
-name: xxx-multi-assignment-cmd
-description:
- Check that assignments in a command affect subsequent assignments
- in the same command
-stdin:
- FOO=abc
- FOO=123 BAR=$FOO
- echo $BAR
-expected-stdout:
- 123
----
-
-name: xxx-exec-environment-1
-description:
- Check to see if exec sets it's environment correctly
-stdin:
- FOO=bar exec env
-expected-stdout-pattern:
- /(^|.*\n)FOO=bar\n/
----
-
-name: xxx-exec-environment-2
-description:
- Check to make sure exec doesn't change environment if a program
- isn't exec-ed
-stdin:
- env > bar1
- FOO=bar exec; env > bar2
- cmp -s bar1 bar2
----
-
-name: xxx-what-do-you-call-this-1
-stdin:
- echo "${foo:-"a"}*"
-expected-stdout:
- a*
----
-
-name: xxx-prefix-strip-1
-stdin:
- foo='a cdef'
- echo ${foo#a c}
-expected-stdout:
- def
----
-
-name: xxx-prefix-strip-2
-stdin:
- set a c
- x='a cdef'
- echo ${x#$*}
-expected-stdout:
- def
----
-
-name: xxx-variable-syntax-1
-stdin:
- echo ${:}
-expected-stderr-pattern:
- /bad substitution/
-expected-exit: 1
----
diff --git a/bin/pdksh/tests/unclass2.t b/bin/pdksh/tests/unclass2.t
deleted file mode 100644
index d9e14822e06..00000000000
--- a/bin/pdksh/tests/unclass2.t
+++ /dev/null
@@ -1,166 +0,0 @@
-name: xxx-subsitution-eval-order
-description:
- Check order of evaluation of expressions
-stdin:
- i=1 x= y=
- set -A A abc def GHI j G k
- echo ${A[x=(i+=1)]#${A[y=(i+=2)]}}
- echo $x $y
-expected-stdout:
- HI
- 2 4
----
-
-name: xxx-set-option-1
-description:
- Check option parsing in set
-stdin:
- set -A -vs A 1 3 2
- echo ${A[*]}
-expected-stderr:
- echo ${A[*]}
-expected-stdout:
- 1 2 3
----
-
-name: xxx-exec-1
-description:
- Check that exec exits for built-ins
-arguments: !-i!
-stdin:
- exec print hi
- echo still herre
-expected-stdout:
- hi
-expected-stderr-pattern: /.*/
----
-
-name: xxx-while-1
-description:
- Check the return value of while loops
- XXX need to do same for for/select/until loops
-stdin:
- i=x
- while [ $i != xxx ] ; do
- i=x$i
- if [ $i = xxx ] ; then
- false
- continue
- fi
- done
- echo loop1=$?
-
- i=x
- while [ $i != xxx ] ; do
- i=x$i
- if [ $i = xxx ] ; then
- false
- break
- fi
- done
- echo loop2=$?
-
- i=x
- while [ $i != xxx ] ; do
- i=x$i
- false
- done
- echo loop3=$?
-expected-stdout:
- loop1=0
- loop2=0
- loop3=1
----
-
-name: xxx-status-1
-description:
- Check that blank lines don't clear $?
-arguments: !-i!
-stdin:
- (exit 1)
- echo $?
- (exit 1)
-
- echo $?
- true
-expected-stdout:
- 1
- 1
-expected-stderr-pattern: /.*/
----
-
-name: xxx-status-2
-description:
- Check that $? is preserved in subshells, includes, traps.
-stdin:
- (exit 1)
-
- echo blank: $?
-
- (exit 2)
- (echo subshell: $?)
-
- echo 'echo include: $?' > foo
- (exit 3)
- . ./foo
-
- trap 'echo trap: $?' ERR
- (exit 4)
- echo exit: $?
-expected-stdout:
- blank: 1
- subshell: 2
- include: 3
- trap: 4
- exit: 4
----
-
-name: xxx-clean-chars-1
-description:
- Check MAGIC character is stuffed correctly
-stdin:
- echo `echo [£`
-expected-stdout:
- [£
----
-
-name: xxx-param-subst-qmark-1
-description:
- Check suppresion of error message with null string. According to
- POSIX, it shouldn't print the error as `word' isn't ommitted.
-stdin:
- unset foo
- x=
- echo x${foo?$x}
-expected-exit: 1
-expected-fail: yes
-expected-stderr-pattern: !/not set/
----
-
-name: xxx-param-_-1
-description:
- Check c flag is set.
-arguments: !-c!echo "[$-]"!
-expected-stdout-pattern: /^\[.*c.*\]$/
----
-
-name: env-prompt
-description:
- Check that prompt not printed when processing ENV
-env-setup: !ENV=./foo!
-perl-setup:
- system("cat > foo << EOF
- XXX=12
- PS1='X '
- false && echo hmmm
- EOF
- ");
-arguments: !-i!
-stdin:
- echo hi${XXX}there
-expected-stdout:
- hi12there
-expected-stderr: !
- X X
----
-
diff --git a/bin/pdksh/tests/version.t b/bin/pdksh/tests/version.t
deleted file mode 100644
index 23d834015fa..00000000000
--- a/bin/pdksh/tests/version.t
+++ /dev/null
@@ -1,8 +0,0 @@
-name: version-1
-description:
- Check version of shell.
-stdin:
- echo $KSH_VERSION
-expected-stdout:
- @(#)PD KSH v5.2.12 96/10/29
----
diff --git a/bin/pdksh/trap.c b/bin/pdksh/trap.c
deleted file mode 100644
index f1efe6451d9..00000000000
--- a/bin/pdksh/trap.c
+++ /dev/null
@@ -1,432 +0,0 @@
-/* $OpenBSD: trap.c,v 1.6 1997/09/01 18:30:13 deraadt Exp $ */
-
-/*
- * signal handling
- */
-
-/* Kludge to avoid bogus re-declaration of sigtraps[] error on AIX 3.2.5 */
-#define FROM_TRAP_C
-#include "sh.h"
-
-/* Table is indexed by signal number
- *
- * The script siglist.sh generates siglist.out, which is a sorted, complete
- * list of signals
- */
-Trap sigtraps[SIGNALS+1] = {
- { SIGEXIT_, "EXIT", "Signal 0" },
-#include "siglist.out" /* generated by siglist.sh */
- { SIGERR_, "ERR", "Error handler" },
- };
-
-static struct sigaction Sigact_ign, Sigact_trap;
-
-void
-inittraps()
-{
-#ifdef HAVE_SYS_SIGLIST
-# ifndef SYS_SIGLIST_DECLARED
- extern char *sys_siglist[];
-# endif
- int i;
-
- /* Use system description, if available, for unknown signals... */
- for (i = 0; i < NSIG; i++)
- if (!sigtraps[i].name && sys_siglist[i][0])
- sigtraps[i].mess = sys_siglist[i];
-#endif /* HAVE_SYS_SIGLIST */
-
- sigemptyset(&Sigact_ign.sa_mask);
- Sigact_ign.sa_flags = KSH_SA_FLAGS;
- Sigact_ign.sa_handler = SIG_IGN;
- Sigact_trap = Sigact_ign;
- Sigact_trap.sa_handler = trapsig;
-
- sigtraps[SIGINT].flags |= TF_DFL_INTR | TF_TTY_INTR;
- sigtraps[SIGQUIT].flags |= TF_DFL_INTR | TF_TTY_INTR;
- sigtraps[SIGTERM].flags |= TF_DFL_INTR;/* not fatal for interactive */
- sigtraps[SIGHUP].flags |= TF_FATAL;
- sigtraps[SIGCHLD].flags |= TF_SHELL_USES;
-
- /* these are always caught so we can clean up any temproary files. */
- setsig(&sigtraps[SIGINT], trapsig, SS_RESTORE_ORIG);
- setsig(&sigtraps[SIGQUIT], trapsig, SS_RESTORE_ORIG);
- setsig(&sigtraps[SIGTERM], trapsig, SS_RESTORE_ORIG);
- setsig(&sigtraps[SIGHUP], trapsig, SS_RESTORE_ORIG);
-}
-
-#ifdef KSH
-static RETSIGTYPE alarm_catcher ARGS((int sig));
-
-void
-alarm_init()
-{
- sigtraps[SIGALRM].flags |= TF_SHELL_USES;
- setsig(&sigtraps[SIGALRM], alarm_catcher,
- SS_RESTORE_ORIG|SS_FORCE|SS_SHTRAP);
-}
-
-static RETSIGTYPE
-alarm_catcher(sig)
- int sig;
-{
- if (ksh_tmout_state == TMOUT_READING) {
- int left = alarm(0);
-
- if (left == 0) {
- ksh_tmout_state = TMOUT_LEAVING;
- intrsig = 1;
- } else
- alarm(left);
- }
- return RETSIGVAL;
-}
-#endif /* KSH */
-
-Trap *
-gettrap(name)
- const char *name;
-{
- int i;
- register Trap *p;
-
- if (digit(*name)) {
- int n;
-
- if (getn(name, &n) && 0 <= n && n < SIGNALS)
- return &sigtraps[n];
- return NULL;
- }
- for (p = sigtraps, i = SIGNALS+1; --i >= 0; p++)
- if (p->name && strcasecmp(p->name, name) == 0)
- return p;
- return NULL;
-}
-
-/*
- * trap signal handler
- */
-RETSIGTYPE
-trapsig(i)
- int i;
-{
- Trap *p = &sigtraps[i];
- int save_errno = errno;
-
- trap = p->set = 1;
- if (p->flags & TF_DFL_INTR)
- intrsig = 1;
- if ((p->flags & TF_FATAL) && !p->trap) {
- fatal_trap = 1;
- intrsig = 1;
- }
- if (p->shtrap)
- (*p->shtrap)(i);
-#ifdef V7_SIGNALS
- if (sigtraps[i].cursig == trapsig) /* this for SIGCHLD,SIGALRM */
- sigaction(i, &Sigact_trap, (struct sigaction *) 0);
-#endif /* V7_SIGNALS */
- errno = save_errno;
- return RETSIGVAL;
-}
-
-/* called when we want to allow the user to ^C out of something - won't
- * work if user has trapped SIGINT.
- */
-void
-intrcheck()
-{
- if (intrsig)
- runtraps(TF_DFL_INTR|TF_FATAL);
-}
-
-/* called after EINTR to check if a signal with normally causes process
- * termination has been received.
- */
-int
-fatal_trap_check()
-{
- int i;
- Trap *p;
-
- /* todo: should check if signal is fatal, not the TF_DFL_INTR flag */
- for (p = sigtraps, i = SIGNALS+1; --i >= 0; p++)
- if (p->set && (p->flags & (TF_DFL_INTR|TF_FATAL)))
- /* return value is used as an exit code */
- return 128 + p->signal;
- return 0;
-}
-
-/* Returns the signal number of any pending traps: ie, a signal which has
- * occured for which a trap has been set or for which the TF_DFL_INTR flag
- * is set.
- */
-int
-trap_pending()
-{
- int i;
- Trap *p;
-
- for (p = sigtraps, i = SIGNALS+1; --i >= 0; p++)
- if (p->set && ((p->trap && p->trap[0])
- || ((p->flags & (TF_DFL_INTR|TF_FATAL))
- && !p->trap)))
- return p->signal;
- return 0;
-}
-
-/*
- * run any pending traps. If intr is set, only run traps that
- * can interrupt commands.
- */
-void
-runtraps(flag)
- int flag;
-{
- int i;
- register Trap *p;
-
-#ifdef KSH
- if (ksh_tmout_state == TMOUT_LEAVING) {
- ksh_tmout_state = TMOUT_EXECUTING;
- warningf(FALSE, "timed out waiting for input");
- unwind(LEXIT);
- } else
- /* XXX: this means the alarm will have no effect if a trap
- * is caught after the alarm() was started...not good.
- */
- ksh_tmout_state = TMOUT_EXECUTING;
-#endif /* KSH */
- if (!flag)
- trap = 0;
- if (flag & TF_DFL_INTR)
- intrsig = 0;
- if (flag & TF_FATAL)
- fatal_trap = 0;
- for (p = sigtraps, i = SIGNALS+1; --i >= 0; p++)
- if (p->set && (!flag
- || ((p->flags & flag) && p->trap == (char *) 0)))
- runtrap(p);
-}
-
-void
-runtrap(p)
- Trap *p;
-{
- int i = p->signal;
- char *trapstr = p->trap;
- int oexstat;
- int UNINITIALIZED(old_changed);
-
- p->set = 0;
- if (trapstr == (char *) 0) { /* SIG_DFL */
- if (p->flags & TF_FATAL) {
- /* eg, SIGHUP */
- exstat = 128 + i;
- unwind(LLEAVE);
- }
- if (p->flags & TF_DFL_INTR) {
- /* eg, SIGINT, SIGQUIT, SIGTERM, etc. */
- exstat = 128 + i;
- unwind(LINTR);
- }
- return;
- }
- if (trapstr[0] == '\0') /* SIG_IGN */
- return;
- if (i == SIGEXIT_ || i == SIGERR_) { /* avoid recursion on these */
- old_changed = p->flags & TF_CHANGED;
- p->flags &= ~TF_CHANGED;
- p->trap = (char *) 0;
- }
- oexstat = exstat;
- command(trapstr);
- exstat = oexstat;
- if (i == SIGEXIT_ || i == SIGERR_) {
- if (p->flags & TF_CHANGED)
- /* don't clear TF_CHANGED */
- afree(trapstr, APERM);
- else
- p->trap = trapstr;
- p->flags |= old_changed;
- }
-}
-
-/* clear pending traps and reset user's trap handlers; used after fork(2) */
-void
-cleartraps()
-{
- int i;
- Trap *p;
-
- trap = 0;
- intrsig = 0;
- fatal_trap = 0;
- for (i = SIGNALS+1, p = sigtraps; --i >= 0; p++) {
- p->set = 0;
- if ((p->flags & TF_USER_SET) && (p->trap && p->trap[0]))
- settrap(p, (char *) 0);
- }
-}
-
-/* restore signals just before an exec(2) */
-void
-restoresigs()
-{
- int i;
- Trap *p;
-
- for (i = SIGNALS+1, p = sigtraps; --i >= 0; p++)
- if (p->flags & (TF_EXEC_IGN|TF_EXEC_DFL))
- setsig(p, (p->flags & TF_EXEC_IGN) ? SIG_IGN : SIG_DFL,
- SS_RESTORE_CURR|SS_FORCE);
-}
-
-void
-settrap(p, s)
- Trap *p;
- char *s;
-{
- handler_t f;
-
- if (p->trap)
- afree(p->trap, APERM);
- p->trap = str_save(s, APERM); /* handles s == 0 */
- p->flags |= TF_CHANGED;
- f = !s ? SIG_DFL : s[0] ? trapsig : SIG_IGN;
-
- p->flags |= TF_USER_SET;
- if ((p->flags & (TF_DFL_INTR|TF_FATAL)) && f == SIG_DFL)
- f = trapsig;
- else if (p->flags & TF_SHELL_USES) {
- if (!(p->flags & TF_ORIG_IGN) || Flag(FTALKING)) {
- /* do what user wants at exec time */
- p->flags &= ~(TF_EXEC_IGN|TF_EXEC_DFL);
- if (f == SIG_IGN)
- p->flags |= TF_EXEC_IGN;
- else
- p->flags |= TF_EXEC_DFL;
- }
- /* assumes handler already set to what shell wants it
- * (normally trapsig, but could be j_sigchld() or SIG_IGN)
- */
- return;
- }
-
- /* todo: should we let user know signal is ignored? how? */
- setsig(p, f, SS_RESTORE_CURR|SS_USER);
-}
-
-/* Called by c_print() when writing to a co-process to ensure SIGPIPE won't
- * kill shell (unless user catches it and exits)
- */
-int
-block_pipe()
-{
- int restore_dfl = 0;
- Trap *p = &sigtraps[SIGPIPE];
-
- if (!(p->flags & (TF_ORIG_IGN|TF_ORIG_DFL))) {
- setsig(p, SIG_IGN, SS_RESTORE_CURR);
- if (p->flags & TF_ORIG_DFL)
- restore_dfl = 1;
- } else if (p->cursig == SIG_DFL) {
- setsig(p, SIG_IGN, SS_RESTORE_CURR);
- restore_dfl = 1; /* restore to SIG_DFL */
- }
- return restore_dfl;
-}
-
-/* Called by c_print() to undo whatever block_pipe() did */
-void
-restore_pipe(restore_dfl)
- int restore_dfl;
-{
- if (restore_dfl)
- setsig(&sigtraps[SIGPIPE], SIG_DFL, SS_RESTORE_CURR);
-}
-
-/* Set action for a signal. Action may not be set if original
- * action was SIG_IGN, depending on the value of flags and
- * FTALKING.
- */
-int
-setsig(p, f, flags)
- Trap *p;
- handler_t f;
- int flags;
-{
- struct sigaction sigact;
-
- if (p->signal == SIGEXIT_ || p->signal == SIGERR_)
- return 1;
-
- /* First time setting this signal? If so, get and note the current
- * setting.
- */
- if (!(p->flags & (TF_ORIG_IGN|TF_ORIG_DFL))) {
- sigaction(p->signal, &Sigact_ign, &sigact);
- p->flags |= sigact.sa_handler == SIG_IGN ?
- TF_ORIG_IGN : TF_ORIG_DFL;
- p->cursig = SIG_IGN;
- }
-
- /* Generally, an ignored signal stays ignored, except if
- * - the user of an interactive shell wants to change it
- * - the shell wants for force a change
- */
- if ((p->flags & TF_ORIG_IGN) && !(flags & SS_FORCE)
- && (!(flags & SS_USER) || !Flag(FTALKING)))
- return 0;
-
- setexecsig(p, flags & SS_RESTORE_MASK);
-
- /* This is here 'cause there should be a way of clearing shtraps, but
- * don't know if this is a sane way of doing it. At the moment,
- * all users of shtrap are lifetime users (SIGCHLD, SIGALRM, SIGWINCH).
- */
- if (!(flags & SS_USER))
- p->shtrap = (handler_t) 0;
- if (flags & SS_SHTRAP) {
- p->shtrap = f;
- f = trapsig;
- }
-
- if (p->cursig != f) {
- p->cursig = f;
- sigemptyset(&sigact.sa_mask);
- sigact.sa_flags = KSH_SA_FLAGS;
- sigact.sa_handler = f;
- sigaction(p->signal, &sigact, (struct sigaction *) 0);
- }
-
- return 1;
-}
-
-/* control what signal is set to before an exec() */
-void
-setexecsig(p, restore)
- Trap *p;
- int restore;
-{
- /* XXX debugging */
- if (!(p->flags & (TF_ORIG_IGN|TF_ORIG_DFL)))
- internal_errorf(1, "setexecsig: unset signal %d(%s)",
- p->signal, p->name);
-
- /* restore original value for exec'd kids */
- p->flags &= ~(TF_EXEC_IGN|TF_EXEC_DFL);
- switch (restore & SS_RESTORE_MASK) {
- case SS_RESTORE_CURR: /* leave things as they currently are */
- break;
- case SS_RESTORE_ORIG:
- p->flags |= p->flags & TF_ORIG_IGN ? TF_EXEC_IGN : TF_EXEC_DFL;
- break;
- case SS_RESTORE_DFL:
- p->flags |= TF_EXEC_DFL;
- break;
- case SS_RESTORE_IGN:
- p->flags |= TF_EXEC_IGN;
- break;
- }
-}
diff --git a/bin/pdksh/tree.c b/bin/pdksh/tree.c
deleted file mode 100644
index 93e3f9d7de7..00000000000
--- a/bin/pdksh/tree.c
+++ /dev/null
@@ -1,656 +0,0 @@
-/* $OpenBSD: tree.c,v 1.5 1997/09/01 18:30:15 deraadt Exp $ */
-
-/*
- * command tree climbing
- */
-
-#include "sh.h"
-
-#define INDENT 4
-
-#define tputc(c, shf) shf_putchar(c, shf);
-static void ptree ARGS((struct op *t, int indent, struct shf *f));
-static void pioact ARGS((struct shf *f, int indent, struct ioword *iop));
-static void tputC ARGS((int c, struct shf *shf));
-static void tputS ARGS((char *wp, struct shf *shf));
-static void vfptreef ARGS((struct shf *shf, int indent, const char *fmt, va_list va));
-static struct ioword **iocopy ARGS((struct ioword **iow, Area *ap));
-static void iofree ARGS((struct ioword **iow, Area *ap));
-
-/*
- * print a command tree
- */
-
-static void
-ptree(t, indent, shf)
- register struct op *t;
- int indent;
- register struct shf *shf;
-{
- register char **w;
- struct ioword **ioact;
- struct op *t1;
-
- Chain:
- if (t == NULL)
- return;
- switch (t->type) {
- case TCOM:
- if (t->vars)
- for (w = t->vars; *w != NULL; )
- fptreef(shf, indent, "%S ", *w++);
- else
- fptreef(shf, indent, "#no-vars# ");
- if (t->args)
- for (w = t->args; *w != NULL; )
- fptreef(shf, indent, "%S ", *w++);
- else
- fptreef(shf, indent, "#no-args# ");
- break;
- case TEXEC:
- t = t->left;
- goto Chain;
- case TPAREN:
- fptreef(shf, indent + 2, "( %T) ", t->left);
- break;
- case TPIPE:
- fptreef(shf, indent, "%T| ", t->left);
- t = t->right;
- goto Chain;
- case TLIST:
- fptreef(shf, indent, "%T%;", t->left);
- t = t->right;
- goto Chain;
- case TOR:
- case TAND:
- fptreef(shf, indent, "%T%s %T",
- t->left, (t->type==TOR) ? "||" : "&&", t->right);
- break;
- case TBANG:
- fptreef(shf, indent, "! ");
- t = t->right;
- goto Chain;
- case TDBRACKET:
- {
- int i;
-
- fptreef(shf, indent, "[[");
- for (i = 0; t->args[i]; i++)
- fptreef(shf, indent, " %S", t->args[i]);
- fptreef(shf, indent, " ]] ");
- break;
- }
-#ifdef KSH
- case TSELECT:
- fptreef(shf, indent, "select %s ", t->str);
- /* fall through */
-#endif /* KSH */
- case TFOR:
- if (t->type == TFOR)
- fptreef(shf, indent, "for %s ", t->str);
- if (t->vars != NULL) {
- fptreef(shf, indent, "in ");
- for (w = t->vars; *w; )
- fptreef(shf, indent, "%S ", *w++);
- fptreef(shf, indent, "%;");
- }
- fptreef(shf, indent + INDENT, "do%N%T", t->left);
- fptreef(shf, indent, "%;done ");
- break;
- case TCASE:
- fptreef(shf, indent, "case %S in", t->str);
- for (t1 = t->left; t1 != NULL; t1 = t1->right) {
- fptreef(shf, indent, "%N(");
- for (w = t1->vars; *w != NULL; w++)
- fptreef(shf, indent, "%S%c", *w,
- (w[1] != NULL) ? '|' : ')');
- fptreef(shf, indent + INDENT, "%;%T%N;;", t1->left);
- }
- fptreef(shf, indent, "%Nesac ");
- break;
- case TIF:
- case TELIF:
- /* 3 == strlen("if ") */
- fptreef(shf, indent + 3, "if %T", t->left);
- for (;;) {
- t = t->right;
- if (t->left != NULL) {
- fptreef(shf, indent, "%;");
- fptreef(shf, indent + INDENT, "then%N%T",
- t->left);
- }
- if (t->right == NULL || t->right->type != TELIF)
- break;
- t = t->right;
- fptreef(shf, indent, "%;");
- /* 5 == strlen("elif ") */
- fptreef(shf, indent + 5, "elif %T", t->left);
- }
- if (t->right != NULL) {
- fptreef(shf, indent, "%;");
- fptreef(shf, indent + INDENT, "else%;%T", t->right);
- }
- fptreef(shf, indent, "%;fi ");
- break;
- case TWHILE:
- case TUNTIL:
- /* 6 == strlen("while"/"until") */
- fptreef(shf, indent + 6, "%s %T",
- (t->type==TWHILE) ? "while" : "until",
- t->left);
- fptreef(shf, indent, "%;do");
- fptreef(shf, indent + INDENT, "%;%T", t->right);
- fptreef(shf, indent, "%;done ");
- break;
- case TBRACE:
- fptreef(shf, indent + INDENT, "{%;%T", t->left);
- fptreef(shf, indent, "%;} ");
- break;
- case TCOPROC:
- fptreef(shf, indent, "%T|& ", t->left);
- break;
- case TASYNC:
- fptreef(shf, indent, "%T& ", t->left);
- break;
- case TFUNCT:
- fptreef(shf, indent, "function %s %T", t->str, t->left);
- break;
- case TTIME:
- fptreef(shf, indent, "time %T", t->left);
- break;
- default:
- fptreef(shf, indent, "<botch>");
- break;
- }
- if ((ioact = t->ioact) != NULL) {
- int need_nl = 0;
-
- while (*ioact != NULL)
- pioact(shf, indent, *ioact++);
- /* Print here documents after everything else... */
- for (ioact = t->ioact; *ioact != NULL; ) {
- struct ioword *iop = *ioact++;
-
- /* name is 0 when tracing (set -x) */
- if ((iop->flag & IOTYPE) == IOHERE && iop->name) {
- struct shf *rshf;
- char buf[1024];
- int n;
-
- tputc('\n', shf);
- if ((rshf = shf_open(iop->name, O_RDONLY, 0, 0))) {
- while ((n = shf_read(buf, sizeof(buf), rshf))
- > 0)
- shf_write(buf, n, shf);
- shf_close(rshf);
- } else
- errorf("can't open %s - %s",
- iop->name, strerror(errno));
- fptreef(shf, indent, "%s", evalstr(iop->delim, 0));
- need_nl = 1;
- }
- }
- /* Last delimiter must be followed by a newline (this often
- * leads to an extra blank line, but its not worth worrying
- * about)
- */
- if (need_nl)
- tputc('\n', shf);
- }
-}
-
-static void
-pioact(shf, indent, iop)
- register struct shf *shf;
- int indent;
- register struct ioword *iop;
-{
- int flag = iop->flag;
- int type = flag & IOTYPE;
- int expected;
-
- expected = (type == IOREAD || type == IORDWR || type == IOHERE) ? 0
- : (type == IOCAT || type == IOWRITE) ? 1
- : (type == IODUP && (iop->unit == !(flag & IORDUP))) ?
- iop->unit
- : iop->unit + 1;
- if (iop->unit != expected)
- tputc('0' + iop->unit, shf);
-
- switch (type) {
- case IOREAD:
- fptreef(shf, indent, "< ");
- break;
- case IOHERE:
- if (flag&IOSKIP)
- fptreef(shf, indent, "<<- ");
- else
- fptreef(shf, indent, "<< ");
- break;
- case IOCAT:
- fptreef(shf, indent, ">> ");
- break;
- case IOWRITE:
- if (flag&IOCLOB)
- fptreef(shf, indent, ">| ");
- else
- fptreef(shf, indent, "> ");
- break;
- case IORDWR:
- fptreef(shf, indent, "<> ");
- break;
- case IODUP:
- if (flag & IORDUP)
- fptreef(shf, indent, "<&");
- else
- fptreef(shf, indent, ">&");
- break;
- }
- /* name/delim are 0 when printing syntax errors */
- if (type == IOHERE) {
- if (iop->delim)
- fptreef(shf, indent, "%S ", iop->delim);
- } else if (iop->name)
- fptreef(shf, indent, (iop->flag & IONAMEXP) ? "%s " : "%S ",
- iop->name);
-}
-
-
-/*
- * variants of fputc, fputs for ptreef and snptreef
- */
-
-static void
-tputC(c, shf)
- register int c;
- register struct shf *shf;
-{
- if ((c&0x60) == 0) { /* C0|C1 */
- tputc((c&0x80) ? '$' : '^', shf);
- tputc(((c&0x7F)|0x40), shf);
- } else if ((c&0x7F) == 0x7F) { /* DEL */
- tputc((c&0x80) ? '$' : '^', shf);
- tputc('?', shf);
- } else
- tputc(c, shf);
-}
-
-static void
-tputS(wp, shf)
- register char *wp;
- register struct shf *shf;
-{
- register int c, quoted=0;
-
- while (1)
- switch ((c = *wp++)) {
- case EOS:
- return;
- case CHAR:
- tputC(*wp++, shf);
- break;
- case QCHAR:
- c = *wp++;
- if (!quoted || (c == '"' || c == '`' || c == '$'))
- tputc('\\', shf);
- tputC(c, shf);
- break;
- case COMSUB:
- tputc('$', shf);
- tputc('(', shf);
- while (*wp != 0)
- tputC(*wp++, shf);
- tputc(')', shf);
- break;
- case EXPRSUB:
- tputc('$', shf);
- tputc('(', shf);
- tputc('(', shf);
- while (*wp != 0)
- tputC(*wp++, shf);
- tputc(')', shf);
- tputc(')', shf);
- break;
- case OQUOTE:
- quoted = 1;
- tputc('"', shf);
- break;
- case CQUOTE:
- quoted = 0;
- tputc('"', shf);
- break;
- case OSUBST:
- tputc('$', shf);
- tputc('{', shf);
- while ((c = *wp++) != 0)
- tputC(c, shf);
- break;
- case CSUBST:
- tputc('}', shf);
- break;
-#ifdef KSH
- case OPAT:
- tputc(*wp++, shf);
- tputc('(', shf);
- break;
- case SPAT:
- tputc('|', shf);
- break;
- case CPAT:
- tputc(')', shf);
- break;
-#endif /* KSH */
- }
-}
-
-/*
- * this is the _only_ way to reliably handle
- * variable args with an ANSI compiler
- */
-/* VARARGS */
-int
-#ifdef HAVE_PROTOTYPES
-fptreef(struct shf *shf, int indent, const char *fmt, ...)
-#else
-fptreef(shf, indent, fmt, va_alist)
- struct shf *shf;
- int indent;
- const char *fmt;
- va_dcl
-#endif
-{
- va_list va;
-
- SH_VA_START(va, fmt);
-
- vfptreef(shf, indent, fmt, va);
- va_end(va);
- return 0;
-}
-
-/* VARARGS */
-char *
-#ifdef HAVE_PROTOTYPES
-snptreef(char *s, int n, const char *fmt, ...)
-#else
-snptreef(s, n, fmt, va_alist)
- char *s;
- int n;
- const char *fmt;
- va_dcl
-#endif
-{
- va_list va;
- struct shf shf;
-
- shf_sopen(s, n, SHF_WR | (s ? 0 : SHF_DYNAMIC), &shf);
-
- SH_VA_START(va, fmt);
- vfptreef(&shf, 0, fmt, va);
- va_end(va);
-
- return shf_sclose(&shf); /* null terminates */
-}
-
-static void
-vfptreef(shf, indent, fmt, va)
- register struct shf *shf;
- int indent;
- const char *fmt;
- register va_list va;
-{
- register int c;
-
- while ((c = *fmt++))
- if (c == '%') {
- register long n;
- register char *p;
- int neg;
-
- switch ((c = *fmt++)) {
- case 'c':
- tputc(va_arg(va, int), shf);
- break;
- case 's':
- p = va_arg(va, char *);
- while (*p)
- tputc(*p++, shf);
- break;
- case 'S': /* word */
- p = va_arg(va, char *);
- tputS(p, shf);
- break;
- case 'd': case 'u': /* decimal */
- n = (c == 'd') ? va_arg(va, int)
- : va_arg(va, unsigned int);
- neg = c=='d' && n<0;
- p = ulton((neg) ? -n : n, 10);
- if (neg)
- *--p = '-';
- while (*p)
- tputc(*p++, shf);
- break;
- case 'T': /* format tree */
- ptree(va_arg(va, struct op *), indent, shf);
- break;
- case ';': /* newline or ; */
- case 'N': /* newline or space */
- if (shf->flags & SHF_STRING) {
- if (c == ';')
- tputc(';', shf);
- tputc(' ', shf);
- } else {
- int i;
-
- tputc('\n', shf);
- for (i = indent; i >= 8; i -= 8)
- tputc('\t', shf);
- for (; i > 0; --i)
- tputc(' ', shf);
- }
- break;
- case 'R':
- pioact(shf, indent, va_arg(va, struct ioword *));
- break;
- default:
- tputc(c, shf);
- break;
- }
- } else
- tputc(c, shf);
-}
-
-/*
- * copy tree (for function definition)
- */
-
-struct op *
-tcopy(t, ap)
- register struct op *t;
- Area *ap;
-{
- register struct op *r;
- register char **tw, **rw;
-
- if (t == NULL)
- return NULL;
-
- r = (struct op *) alloc(sizeof(struct op), ap);
-
- r->type = t->type;
- r->u.evalflags = t->u.evalflags;
-
- r->str = t->type == TCASE ? wdcopy(t->str, ap) : str_save(t->str, ap);
-
- if (t->vars == NULL)
- r->vars = NULL;
- else {
- for (tw = t->vars; *tw++ != NULL; )
- ;
- rw = r->vars = (char **)
- alloc((int)(tw - t->vars) * sizeof(*tw), ap);
- for (tw = t->vars; *tw != NULL; )
- *rw++ = wdcopy(*tw++, ap);
- *rw = NULL;
- }
-
- if (t->args == NULL)
- r->args = NULL;
- else {
- for (tw = t->args; *tw++ != NULL; )
- ;
- rw = r->args = (char **)
- alloc((int)(tw - t->args) * sizeof(*tw), ap);
- for (tw = t->args; *tw != NULL; )
- *rw++ = wdcopy(*tw++, ap);
- *rw = NULL;
- }
-
- r->ioact = (t->ioact == NULL) ? NULL : iocopy(t->ioact, ap);
-
- r->left = tcopy(t->left, ap);
- r->right = tcopy(t->right, ap);
-
- return r;
-}
-
-char *
-wdcopy(wp, ap)
- const char *wp;
- Area *ap;
-{
- size_t len = wdscan(wp, EOS) - wp;
- return memcpy(alloc(len, ap), wp, len);
-}
-
-/* return the position of prefix c in wp plus 1 */
-char *
-wdscan(wp, c)
- register const char *wp;
- register int c;
-{
- register int nest = 0;
-
- while (1)
- switch (*wp++) {
- case EOS:
- return (char *) wp;
- case CHAR:
- case QCHAR:
- wp++;
- break;
- case COMSUB:
- case EXPRSUB:
- while (*wp++ != 0)
- ;
- break;
- case OQUOTE:
- case CQUOTE:
- break;
- case OSUBST:
- nest++;
- while (*wp++ != '\0')
- ;
- break;
- case CSUBST:
- if (c == CSUBST && nest == 0)
- return (char *) wp;
- nest--;
- break;
-#ifdef KSH
- case OPAT:
- nest++;
- wp++;
- break;
- case SPAT:
- case CPAT:
- if (c == wp[-1] && nest == 0)
- return (char *) wp;
- if (wp[-1] == CPAT)
- nest--;
- break;
-#endif /* KSH */
- }
-}
-
-static struct ioword **
-iocopy(iow, ap)
- register struct ioword **iow;
- Area *ap;
-{
- register struct ioword **ior;
- register int i;
-
- for (ior = iow; *ior++ != NULL; )
- ;
- ior = (struct ioword **) alloc((int)(ior - iow) * sizeof(*ior), ap);
-
- for (i = 0; iow[i] != NULL; i++) {
- register struct ioword *p, *q;
-
- p = iow[i];
- q = (struct ioword *) alloc(sizeof(*p), ap);
- ior[i] = q;
- *q = *p;
- if (p->name != (char *) 0)
- q->name = wdcopy(p->name, ap);
- if (p->delim != (char *) 0)
- q->delim = wdcopy(p->delim, ap);
- }
- ior[i] = NULL;
-
- return ior;
-}
-
-/*
- * free tree (for function definition)
- */
-
-void
-tfree(t, ap)
- register struct op *t;
- Area *ap;
-{
- register char **w;
-
- if (t == NULL)
- return;
-
- if (t->str != NULL)
- afree((void*)t->str, ap);
-
- if (t->vars != NULL) {
- for (w = t->vars; *w != NULL; w++)
- afree((void*)*w, ap);
- afree((void*)t->vars, ap);
- }
-
- if (t->args != NULL) {
- for (w = t->args; *w != NULL; w++)
- afree((void*)*w, ap);
- afree((void*)t->args, ap);
- }
-
- if (t->ioact != NULL)
- iofree(t->ioact, ap);
-
- tfree(t->left, ap);
- tfree(t->right, ap);
-
- afree((void*)t, ap);
-}
-
-static void
-iofree(iow, ap)
- struct ioword **iow;
- Area *ap;
-{
- register struct ioword **iop;
- register struct ioword *p;
-
- for (iop = iow; (p = *iop++) != NULL; ) {
- if (p->name != NULL)
- afree((void*)p->name, ap);
- afree((void*)p, ap);
- }
-}
diff --git a/bin/pdksh/tree.h b/bin/pdksh/tree.h
deleted file mode 100644
index 863061dd91d..00000000000
--- a/bin/pdksh/tree.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/* $OpenBSD: tree.h,v 1.2 1996/08/19 20:09:02 downsj Exp $ */
-
-/*
- * command trees for compile/execute
- */
-
-/* $From: tree.h,v 1.3 1994/05/31 13:34:34 michael Exp $ */
-
-#define NOBLOCK ((struct op *)NULL)
-#define NOWORD ((char *)NULL)
-#define NOWORDS ((char **)NULL)
-
-/*
- * Description of a command or an operation on commands.
- */
-struct op {
- short type; /* operation type, see below */
- union { /* WARNING: newtp(), tcopy() use evalflags = 0 to clear union */
- short evalflags; /* TCOM: arg expansion eval() flags */
- short ksh_func; /* TFUNC: function x (vs x()) */
- } u;
- char **args; /* arguments to a command */
- char **vars; /* variable assignments */
- struct ioword **ioact; /* IO actions (eg, < > >>) */
- struct op *left, *right; /* descendents */
- char *str; /* word for case; identifier for for,
- * select, and functions;
- * path to execute for TEXEC
- */
-};
-
-/* Tree.type values */
-#define TEOF 0
-#define TCOM 1 /* command */
-#define TPAREN 2 /* (c-list) */
-#define TPIPE 3 /* a | b */
-#define TLIST 4 /* a ; b */
-#define TOR 5 /* || */
-#define TAND 6 /* && */
-#define TBANG 7 /* ! */
-#define TDBRACKET 8 /* [[ .. ]] */
-#define TFOR 9
-#define TSELECT 10
-#define TCASE 11
-#define TIF 12
-#define TWHILE 13
-#define TUNTIL 14
-#define TELIF 15
-#define TPAT 16 /* pattern in case */
-#define TBRACE 17 /* {c-list} */
-#define TASYNC 18 /* c & */
-#define TFUNCT 19 /* function name { command; } */
-#define TTIME 20 /* time pipeline */
-#define TEXEC 21 /* fork/exec eval'd TCOM */
-#define TCOPROC 22 /* coprocess |& */
-
-/*
- * prefix codes for words in command tree
- */
-#define EOS 0 /* end of string */
-#define CHAR 1 /* unquoted character */
-#define QCHAR 2 /* quoted character */
-#define COMSUB 3 /* $() substitution (0 terminated) */
-#define EXPRSUB 4 /* $(()) substitution (0 terminated) */
-#define OQUOTE 5 /* opening " or ' */
-#define CQUOTE 6 /* closing " or ' */
-#define OSUBST 7 /* opening ${ substitution */
-#define CSUBST 8 /* closing } of above */
-#define OPAT 9 /* open pattern: *(, @(, etc. */
-#define SPAT 10 /* seperate pattern: | */
-#define CPAT 11 /* close pattern: ) */
-
-/*
- * IO redirection
- */
-struct ioword {
- int unit; /* unit affected */
- int flag; /* action (below) */
- char *name; /* file name */
- char *delim; /* delimiter for <<,<<- */
-};
-
-/* ioword.flag - type of redirection */
-#define IOTYPE 0xF /* type: bits 0:3 */
-#define IOREAD 0x1 /* < */
-#define IOWRITE 0x2 /* > */
-#define IORDWR 0x3 /* <>: todo */
-#define IOHERE 0x4 /* << (here file) */
-#define IOCAT 0x5 /* >> */
-#define IODUP 0x6 /* <&/>& */
-#define IOEVAL BIT(4) /* expand in << */
-#define IOSKIP BIT(5) /* <<-, skip ^\t* */
-#define IOCLOB BIT(6) /* >|, override -o noclobber */
-#define IORDUP BIT(7) /* x<&y (as opposed to x>&y) */
-#define IONAMEXP BIT(8) /* name has been expanded */
-
-/* execute/exchild flags */
-#define XEXEC BIT(0) /* execute without forking */
-#define XFORK BIT(1) /* fork before executing */
-#define XBGND BIT(2) /* command & */
-#define XPIPEI BIT(3) /* input is pipe */
-#define XPIPEO BIT(4) /* output is pipe */
-#define XPIPE (XPIPEI|XPIPEO) /* member of pipe */
-#define XXCOM BIT(5) /* `...` command */
-#define XPCLOSE BIT(6) /* exchild: close close_fd in parent */
-#define XCCLOSE BIT(7) /* exchild: close close_fd in child */
-#define XERROK BIT(8) /* non-zero exit ok (for set -e) */
-#define XCOPROC BIT(9) /* starting a co-process */
-
-/*
- * flags to control expansion of words (assumed by t->evalflags to fit
- * in a short)
- */
-#define DOBLANK BIT(0) /* perform blank interpretation */
-#define DOGLOB BIT(1) /* expand [?* */
-#define DOPAT BIT(2) /* quote *?[ */
-#define DOTILDE BIT(3) /* normal ~ expansion (first char) */
-#define DONTRUNCOMMAND BIT(4) /* do not run $(command) things */
-#define DOASNTILDE BIT(5) /* assignment ~ expansion (after =, :) */
-#define DOBRACE_ BIT(6) /* used by expand(): do brace expansion */
-#define DOMAGIC_ BIT(7) /* used by expand(): string contains MAGIC */
-#define DOTEMP_ BIT(8) /* ditto : in word part of ${..[%#=?]..} */
-#define DOVACHECK BIT(9) /* var assign check (for typeset, set, etc) */
-#define DOMARKDIRS BIT(10) /* force markdirs behaviour */
-
-/*
- * The arguments of [[ .. ]] expressions are kept in t->args[] and flags
- * indicating how the arguments have been munged are kept in t->vars[].
- * The contents of t->vars[] are stuffed strings (so they can be treated
- * like all other t->vars[]) in which the second character is the one that
- * is examined. The DB_* defines are the values for these second characters.
- */
-#define DB_NORM 1 /* normal argument */
-#define DB_OR 2 /* || -> -o conversion */
-#define DB_AND 3 /* && -> -a conversion */
-#define DB_BE 4 /* an inserted -BE */
-#define DB_PAT 5 /* a pattern argument */
diff --git a/bin/pdksh/tty.c b/bin/pdksh/tty.c
deleted file mode 100644
index 00a94cd3ae6..00000000000
--- a/bin/pdksh/tty.c
+++ /dev/null
@@ -1,179 +0,0 @@
-/* $OpenBSD: tty.c,v 1.2 1996/10/01 02:05:51 downsj Exp $ */
-
-#include "sh.h"
-#include "ksh_stat.h"
-#define EXTERN
-#include "tty.h"
-#undef EXTERN
-
-int
-get_tty(fd, ts)
- int fd;
- TTY_state *ts;
-{
- int ret;
-
-# ifdef HAVE_TERMIOS_H
- ret = tcgetattr(fd, ts);
-# else /* HAVE_TERIOS_H */
-# ifdef HAVE_TERMIO_H
- ret = ioctl(fd, TCGETA, ts);
-# else /* HAVE_TERMIO_H */
- ret = ioctl(fd, TIOCGETP, &ts->sgttyb);
-# ifdef TIOCGATC
- if (ioctl(fd, TIOCGATC, &ts->lchars) < 0)
- ret = -1;
-# else
- if (ioctl(fd, TIOCGETC, &ts->tchars) < 0)
- ret = -1;
-# ifdef TIOCGLTC
- if (ioctl(fd, TIOCGLTC, &ts->ltchars) < 0)
- ret = -1;
-# endif /* TIOCGLTC */
-# endif /* TIOCGATC */
-# endif /* HAVE_TERMIO_H */
-# endif /* HAVE_TERIOS_H */
- return ret;
-}
-
-int
-set_tty(fd, ts, flags)
- int fd;
- TTY_state *ts;
- int flags;
-{
- int ret = 0;
-
-# ifdef HAVE_TERMIOS_H
- ret = tcsetattr(fd, TCSADRAIN, ts);
-# else /* HAVE_TERIOS_H */
-# ifdef HAVE_TERMIO_H
-# ifndef TCSETAW /* e.g. Cray-2 */
- /* first wait for output to drain */
-# ifdef TCSBRK
- if (ioctl(tty_fd, TCSBRK, 1) < 0)
- ret = -1;
-# else /* the following kludge is minimally intrusive, but sometimes fails */
- if (flags & TF_WAIT)
- sleep((unsigned)1); /* fake it */
-# endif
-# endif /* !TCSETAW */
-# if defined(_BSD_SYSV) || !defined(TCSETAW)
-/* _BSD_SYSV must force TIOCSETN instead of TIOCSETP (preserve type-ahead) */
- if (ioctl(tty_fd, TCSETA, ts) < 0)
- ret = -1;
-# else
- if (ioctl(tty_fd, TCSETAW, ts) < 0)
- ret = -1;
-# endif
-# else /* HAVE_TERMIO_H */
-# if defined(__mips) && (defined(_SYSTYPE_BSD43) || defined(__SYSTYPE_BSD43))
- /* Under RISC/os 5.00, bsd43 environment, after a tty driver
- * generated interrupt (eg, INTR, TSTP), all output to tty is
- * lost until a SETP is done (there must be a better way of
- * doing this...).
- */
- if (flags & TF_MIPSKLUDGE)
- ret = ioctl(fd, TIOCSETP, &ts->sgttyb);
- else
-# endif /* _SYSTYPE_BSD43 */
- ret = ioctl(fd, TIOCSETN, &ts->sgttyb);
-# ifdef TIOCGATC
- if (ioctl(fd, TIOCSATC, &ts->lchars) < 0)
- ret = -1;
-# else
- if (ioctl(fd, TIOCSETC, &ts->tchars) < 0)
- ret = -1;
-# ifdef TIOCGLTC
- if (ioctl(fd, TIOCSLTC, &ts->ltchars) < 0)
- ret = -1;
-# endif /* TIOCGLTC */
-# endif /* TIOCGATC */
-# endif /* HAVE_TERMIO_H */
-# endif /* HAVE_TERIOS_H */
- return ret;
-}
-
-
-/* Initialize tty_fd. Used for saving/reseting tty modes upon
- * foreground job completion and for setting up tty process group.
- */
-void
-tty_init(init_ttystate)
- int init_ttystate;
-{
- int do_close = 1;
- int tfd;
-
- if (tty_fd >= 0) {
- close(tty_fd);
- tty_fd = -1;
- }
- tty_devtty = 1;
-
- /* SCO can't job control on /dev/tty, so don't try... */
-#if !defined(__SCO__)
- if ((tfd = open("/dev/tty", O_RDWR, 0)) < 0) {
-#ifdef __NeXT
- /* rlogin on NeXT boxes does not set up the controlling tty,
- * so force it to be done here...
- */
- {
- extern char *ttyname ARGS((int));
- char *s = ttyname(isatty(2) ? 2 : 0);
- int fd;
-
- if (s && (fd = open(s, O_RDWR, 0)) >= 0) {
- close(fd);
- tfd = open("/dev/tty", O_RDWR, 0);
- }
- }
-#endif /* __NeXT */
-
-/* X11R5 xterm on mips doesn't set controlling tty properly - temporary hack */
-# if !defined(__mips) || !(defined(_SYSTYPE_BSD43) || defined(__SYSTYPE_BSD43))
- if (tfd < 0) {
- tty_devtty = 0;
- warningf(FALSE,
- "No controlling tty (open /dev/tty: %s)",
- strerror(errno));
- }
-# endif /* __mips */
- }
-#else /* !__SCO__ */
- tfd = -1;
-#endif /* __SCO__ */
-
- if (tfd < 0) {
- do_close = 0;
- if (isatty(0))
- tfd = 0;
- else if (isatty(2))
- tfd = 2;
- else {
- warningf(FALSE, "Can't find tty file descriptor");
- return;
- }
- }
- if ((tty_fd = ksh_dupbase(tfd, FDBASE)) < 0) {
- warningf(FALSE, "j_ttyinit: dup of tty fd failed: %s",
- strerror(errno));
- } else if (fd_clexec(tty_fd) < 0) {
- warningf(FALSE, "j_ttyinit: can't set close-on-exec flag: %s",
- strerror(errno));
- close(tty_fd);
- tty_fd = -1;
- } else if (init_ttystate)
- get_tty(tty_fd, &tty_state);
- if (do_close)
- close(tfd);
-}
-
-void
-tty_close()
-{
- if (tty_fd >= 0) {
- close(tty_fd);
- tty_fd = -1;
- }
-}
diff --git a/bin/pdksh/tty.h b/bin/pdksh/tty.h
deleted file mode 100644
index a6cd2dae1e9..00000000000
--- a/bin/pdksh/tty.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/* $OpenBSD: tty.h,v 1.2 1996/11/21 07:59:36 downsj Exp $ */
-
-/*
- tty.h -- centralized definitions for a variety of terminal interfaces
-
- created by DPK, Oct. 1986
-
- Rearranged to work with autoconf, added TTY_state, get_tty/set_tty
- Michael Rendell, May '94
-
- last edit: 30-Jul-1987 D A Gwyn
-*/
-
-/* some useful #defines */
-#ifdef EXTERN
-# define I__(i) = i
-#else
-# define I__(i)
-# define EXTERN extern
-# define EXTERN_DEFINED
-#endif
-
-/* Don't know of a system on which including sys/ioctl.h with termios.h
- * causes problems. If there is one, these lines need to be deleted and
- * aclocal.m4 needs to have stuff un-commented.
- */
-#ifdef SYS_IOCTL_WITH_TERMIOS
-# define SYS_IOCTL_WITH_TERMIOS
-#endif /* SYS_IOCTL_WITH_TERMIOS */
-#ifdef SYS_IOCTL_WITH_TERMIO
-# define SYS_IOCTL_WITH_TERMIO
-#endif /* SYS_IOCTL_WITH_TERMIO */
-
-#ifdef HAVE_TERMIOS_H
-# include <termios.h>
-# ifdef SYS_IOCTL_WITH_TERMIOS
-# if !(defined(sun) && !defined(__svr4__)) /* too many warnings on sunos */
- /* Need to include sys/ioctl.h on some systems to get the TIOCGWINSZ
- * stuff (eg, digital unix).
- */
-# include <sys/ioctl.h>
-# endif /* !(sun && !__svr4__) */
-# endif /* SYS_IOCTL_WITH_TERMIOS */
-typedef struct termios TTY_state;
-#else
-# ifdef HAVE_TERMIO_H
-# include <termio.h>
-# ifdef SYS_IOCTL_WITH_TERMIO
-# include <sys/ioctl.h> /* see comment above in termios stuff */
-# endif /* SYS_IOCTL_WITH_TERMIO */
-# if _BSD_SYSV /* BRL UNIX System V emulation */
-# ifndef NTTYDISC
-# define TIOCGETD _IOR( 't', 0, int )
-# define TIOCSETD _IOW( 't', 1, int )
-# define NTTYDISC 2
-# endif
-# ifndef TIOCSTI
-# define TIOCSTI _IOW( 't', 114, char )
-# endif
-# ifndef TIOCSPGRP
-# define TIOCSPGRP _IOW( 't', 118, int )
-# endif
-# endif /* _BSD_SYSV */
-typedef struct termio TTY_state;
-# else /* HAVE_TERMIO_H */
-/* Assume BSD tty stuff. Uses TIOCGETP, TIOCSETN; uses TIOCGATC/TIOCSATC if
- * available, otherwise it uses TIOCGETC/TIOCSETC (also uses TIOCGLTC/TIOCSLTC
- * if available)
- */
-# ifdef _MINIX
-# include <sgtty.h>
-# define TIOCSETN TIOCSETP
-# else
-# include <sys/ioctl.h>
-# endif
-typedef struct {
- struct sgttyb sgttyb;
-# ifdef TIOCGATC
- struct lchars lchars;
-# else /* TIOCGATC */
- struct tchars tchars;
-# ifdef TIOCGLTC
- struct ltchars ltchars;
-# endif /* TIOCGLTC */
-# endif /* TIOCGATC */
-} TTY_state;
-# endif /* HAVE_TERMIO_H */
-#endif /* HAVE_TERMIOS_H */
-
-/* Flags for set_tty() */
-#define TF_NONE 0x00
-#define TF_WAIT 0x01 /* drain output, even it requires sleep() */
-#define TF_MIPSKLUDGE 0x02 /* kludge to unwedge RISC/os 5.0 tty driver */
-
-EXTERN int tty_fd I__(-1); /* dup'd tty file descriptor */
-EXTERN int tty_devtty; /* true if tty_fd is from /dev/tty */
-EXTERN TTY_state tty_state; /* saved tty state */
-
-extern int get_tty ARGS((int fd, TTY_state *ts));
-extern int set_tty ARGS((int fd, TTY_state *ts, int flags));
-extern void tty_init ARGS((int init_ttystate));
-extern void tty_close ARGS((void));
-
-/* be sure not to interfere with anyone else's idea about EXTERN */
-#ifdef EXTERN_DEFINED
-# undef EXTERN_DEFINED
-# undef EXTERN
-#endif
-#undef I__
diff --git a/bin/pdksh/var.c b/bin/pdksh/var.c
deleted file mode 100644
index 8350846a148..00000000000
--- a/bin/pdksh/var.c
+++ /dev/null
@@ -1,1137 +0,0 @@
-/* $OpenBSD: var.c,v 1.6 1997/09/01 18:30:16 deraadt Exp $ */
-
-#include "sh.h"
-#include "ksh_time.h"
-#include "ksh_limval.h"
-#include "ksh_stat.h"
-#include <ctype.h>
-
-/*
- * Variables
- *
- * WARNING: unreadable code, needs a rewrite
- *
- * if (flag&INTEGER), val.i contains integer value, and type contains base.
- * otherwise, (val.s + type) contains string value.
- * if (flag&EXPORT), val.s contains "name=value" for E-Z exporting.
- */
-static struct tbl vtemp;
-static struct table specials;
-static char *formatstr ARGS((struct tbl *vp, const char *s));
-static void export ARGS((struct tbl *vp, const char *val));
-static int special ARGS((const char *name));
-static void getspec ARGS((struct tbl *vp));
-static void setspec ARGS((struct tbl *vp));
-static void unsetspec ARGS((struct tbl *vp));
-static struct tbl *arraysearch ARGS((struct tbl *, int));
-
-/*
- * create a new block for function calls and simple commands
- * assume caller has allocated and set up e->loc
- */
-void
-newblock()
-{
- register struct block *l;
- static char *const empty[] = {null};
-
- l = (struct block *) alloc(sizeof(struct block), ATEMP);
- ainit(&l->area);
- if (!e->loc) {
- l->argc = 0;
- l->argv = (char **) empty;
- } else {
- l->argc = e->loc->argc;
- l->argv = e->loc->argv;
- }
- l->exit = l->error = NULL;
- tinit(&l->vars, &l->area, 0);
- tinit(&l->funs, &l->area, 0);
- l->next = e->loc;
- e->loc = l;
-}
-
-/*
- * pop a block handling special variables
- */
-void
-popblock()
-{
- register struct block *l = e->loc;
- register struct tbl *vp, **vpp = l->vars.tbls, *vq;
- register int i;
-
- e->loc = l->next; /* pop block */
- for (i = l->vars.size; --i >= 0; )
- if ((vp = *vpp++) != NULL && (vp->flag&SPECIAL))
- if ((vq = global(vp->name))->flag & ISSET)
- setspec(vq);
- else
- unsetspec(vq);
- afreeall(&l->area);
- afree(l, ATEMP);
-}
-
-/* called by main() to initialize variable data structures */
-void
-initvar()
-{
- static const struct {
- const char *name;
- int v;
- } names[] = {
- { "COLUMNS", V_COLUMNS },
- { "IFS", V_IFS },
- { "OPTIND", V_OPTIND },
- { "PATH", V_PATH },
- { "POSIXLY_CORRECT", V_POSIXLY_CORRECT },
- { "TMPDIR", V_TMPDIR },
-#ifdef HISTORY
- { "HISTFILE", V_HISTFILE },
- { "HISTSIZE", V_HISTSIZE },
-#endif /* HISTORY */
-#ifdef EDIT
- { "EDITOR", V_EDITOR },
- { "VISUAL", V_VISUAL },
-#endif /* EDIT */
-#ifdef KSH
- { "MAIL", V_MAIL },
- { "MAILCHECK", V_MAILCHECK },
- { "MAILPATH", V_MAILPATH },
- { "RANDOM", V_RANDOM },
- { "SECONDS", V_SECONDS },
- { "TMOUT", V_TMOUT },
-#endif /* KSH */
- { (char *) 0, 0 }
- };
- int i;
- struct tbl *tp;
-
- tinit(&specials, APERM, 32); /* must be 2^n (currently 16 speciasl) */
- for (i = 0; names[i].name; i++) {
- tp = tenter(&specials, names[i].name, hash(names[i].name));
- tp->flag = DEFINED|ISSET;
- tp->type = names[i].v;
- }
-}
-
-/* Used to calculate an array index for global()/local(). Sets *arrayp to
- * non-zero if this is an array, sets *valp to the array index, returns
- * the basename of the array.
- */
-const char *
-array_index_calc(n, arrayp, valp)
- const char *n;
- bool_t *arrayp;
- int *valp;
-{
- const char *p;
- int len;
-
- *arrayp = FALSE;
- p = skip_varname(n, FALSE);
- if (p != n && *p == '[' && (len = array_ref_len(p))) {
- char *sub, *tmp;
- long rval;
-
- /* Calculate the value of the subscript */
- *arrayp = TRUE;
- tmp = str_nsave(p+1, len-2, ATEMP);
- sub = substitute(tmp, 0);
- afree(tmp, ATEMP);
- n = str_nsave(n, p - n, ATEMP);
- evaluate(sub, &rval, FALSE);
- if (rval < 0 || rval > ARRAYMAX)
- errorf("%s: subscript out of range", n);
- *valp = rval;
- afree(sub, ATEMP);
- }
- return n;
-}
-
-/*
- * Search for variable, if not found create globally.
- */
-struct tbl *
-global(n)
- register const char *n;
-{
- register struct block *l = e->loc;
- register struct tbl *vp;
- register int c;
- unsigned h;
- bool_t array;
- int val;
-
- /* Check to see if this is an array */
- n = array_index_calc(n, &array, &val);
- h = hash(n);
- c = n[0];
- if (!letter(c)) {
- if (array)
- errorf("bad substitution");
- vp = &vtemp;
- vp->flag = (DEFINED|RDONLY);
- vp->type = 0;
- vp->areap = ATEMP;
- *vp->name = c;
- if (digit(c)) {
- for (c = 0; digit(*n); n++)
- c = c*10 + *n-'0';
- if (c <= l->argc)
- setstr(vp, l->argv[c]);
- return vp;
- }
- if (n[1] != '\0')
- return vp;
- vp->flag |= ISSET|INTEGER;
- switch (c) {
- case '$':
- vp->val.i = kshpid;
- break;
- case '!':
- /* If no job, expand to nothing */
- if ((vp->val.i = j_async()) == 0)
- vp->flag &= ~(ISSET|INTEGER);
- break;
- case '?':
- vp->val.i = exstat;
- break;
- case '#':
- vp->val.i = l->argc;
- break;
- case '-':
- vp->flag &= ~INTEGER;
- vp->val.s = getoptions();
- break;
- default:
- vp->flag &= ~(ISSET|INTEGER);
- }
- return vp;
- }
- for (l = e->loc; ; l = l->next) {
- vp = tsearch(&l->vars, n, h);
- if (vp != NULL)
- if (array)
- return arraysearch(vp, val);
- else
- return vp;
- if (l->next == NULL)
- break;
- }
- vp = tenter(&l->vars, n, h);
- if (array)
- vp = arraysearch(vp, val);
- vp->flag |= DEFINED;
- if (special(n))
- vp->flag |= SPECIAL;
- return vp;
-}
-
-/*
- * Search for local variable, if not found create locally.
- */
-struct tbl *
-local(n, copy)
- register const char *n;
- bool_t copy;
-{
- register struct block *l = e->loc;
- register struct tbl *vp;
- unsigned h;
- bool_t array;
- int val;
-
- /* Check to see if this is an array */
- n = array_index_calc(n, &array, &val);
- h = hash(n);
- if (!letter(*n)) {
- vp = &vtemp;
- vp->flag = DEFINED|RDONLY;
- vp->type = 0;
- vp->areap = ATEMP;
- return vp;
- }
- vp = tenter(&l->vars, n, h);
- if (copy && !(vp->flag & DEFINED)) {
- struct block *ll = l;
- struct tbl *vq = (struct tbl *) 0;
-
- while ((ll = ll->next) && !(vq = tsearch(&ll->vars, n, h)))
- ;
- if (vq) {
- vp->flag |= vq->flag & (EXPORT|INTEGER|RDONLY
- |LJUST|RJUST|ZEROFIL
- |LCASEV|UCASEV_AL|INT_U|INT_L);
- if (vq->flag & INTEGER)
- vp->type = vq->type;
- vp->u2.field = vq->u2.field;
- }
- }
- if (array)
- vp = arraysearch(vp, val);
- vp->flag |= DEFINED;
- if (special(n))
- vp->flag |= SPECIAL;
- return vp;
-}
-
-/* get variable string value */
-char *
-str_val(vp)
- register struct tbl *vp;
-{
- char *s;
-
- if ((vp->flag&SPECIAL))
- getspec(vp);
- if (!(vp->flag&ISSET))
- s = null; /* special to dollar() */
- else if (!(vp->flag&INTEGER)) /* string source */
- s = vp->val.s + vp->type;
- else { /* integer source */
- /* worst case number length is when base=2, so use BITS(long) */
- /* minus base # number null */
- static char strbuf[1 + 2 + 1 + BITS(long) + 1];
- const char *digits = (vp->flag & UCASEV_AL) ?
- "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- : "0123456789abcdefghijklmnopqrstuvwxyz";
- register unsigned long n;
- register int base;
-
- s = strbuf + sizeof(strbuf);
- if (vp->flag & INT_U)
- n = (unsigned long) vp->val.i;
- else
- n = (vp->val.i < 0) ? -vp->val.i : vp->val.i;
- base = (vp->type == 0) ? 10 : vp->type;
-
- *--s = '\0';
- do {
- *--s = digits[n % base];
- n /= base;
- } while (n != 0);
- if (base != 10) {
- *--s = '#';
- *--s = digits[base % 10];
- if (base >= 10)
- *--s = digits[base / 10];
- }
- if (!(vp->flag & INT_U) && vp->val.i < 0)
- *--s = '-';
- if (vp->flag & (RJUST|LJUST)) /* case already dealt with */
- s = formatstr(vp, s);
- }
- return s;
-}
-
-/* get variable integer value, with error checking */
-long
-intval(vp)
- register struct tbl *vp;
-{
- long num;
- int base;
-
- base = getint(vp, &num);
- if (base == -1)
- /* XXX check calls - is error here ok by POSIX? */
- errorf("%s: bad number", str_val(vp));
- return num;
-}
-
-/* set variable to string value */
-void
-setstr(vq, s)
- register struct tbl *vq;
- const char *s;
-{
- if (!(vq->flag&INTEGER)) { /* string dest */
- if ((vq->flag&ALLOC)) {
- /* debugging */
- if (s >= vq->val.s
- && s <= vq->val.s + strlen(vq->val.s))
- internal_errorf(TRUE,
- "setstr: %s=%s: assigning to self",
- vq->name, s);
- afree((void*)vq->val.s, vq->areap);
- }
- vq->flag &= ~(ISSET|ALLOC);
- vq->type = 0;
- if (s && (vq->flag & (UCASEV_AL|LCASEV|LJUST|RJUST)))
- s = formatstr(vq, s);
- if ((vq->flag&EXPORT))
- export(vq, s);
- else {
- vq->val.s = str_save(s, vq->areap);
- if (vq->val.s) /* <sjg> don't lie */
- vq->flag |= ALLOC;
- }
- } else /* integer dest */
- /* XXX is this correct? */
- v_evaluate(vq, s, FALSE);
- vq->flag |= ISSET;
- if ((vq->flag&SPECIAL))
- setspec(vq);
-}
-
-/* set variable to integer */
-void
-setint(vq, n)
- register struct tbl *vq;
- long n;
-{
- if (!(vq->flag&INTEGER)) {
- register struct tbl *vp = &vtemp;
- vp->flag = (ISSET|INTEGER);
- vp->type = 0;
- vp->areap = ATEMP;
- vp->val.i = n;
- setstr(vq, str_val(vp));
- } else
- vq->val.i = n;
- vq->flag |= ISSET;
- if ((vq->flag&SPECIAL))
- setspec(vq);
-}
-
-int
-getint(vp, nump)
- struct tbl *vp;
- long *nump;
-{
- register char *s;
- register int c;
- int base, neg;
- int have_base = 0;
- long num;
-
- if (vp->flag&SPECIAL)
- getspec(vp);
- /* XXX is it possible for ISSET to be set and val.s to be 0? */
- if (!(vp->flag&ISSET) || (!(vp->flag&INTEGER) && vp->val.s == NULL))
- return -1;
- if (vp->flag&INTEGER) {
- *nump = vp->val.i;
- return vp->type;
- }
- s = vp->val.s + vp->type;
- if (s == NULL) /* redundent given initial test */
- s = null;
- base = 10;
- num = 0;
- neg = 0;
- for (c = *s++; c ; c = *s++) {
- if (c == '-') {
- neg++;
- } else if (c == '#') {
- base = (int) num;
- if (have_base || base < 2 || base > 36)
- return -1;
- num = 0;
- have_base = 1;
- } else if (letnum(c)) {
- if (isdigit(c))
- c -= '0';
- else if (islower(c))
- c -= 'a' - 10; /* todo: assumes ascii */
- else if (isupper(c))
- c -= 'A' - 10; /* todo: assumes ascii */
- else
- c = -1; /* _: force error */
- if (c < 0 || c >= base)
- return -1;
- num = num * base + c;
- } else
- return -1;
- }
- if (neg)
- num = -num;
- *nump = num;
- return base;
-}
-
-/* convert variable vq to integer variable, setting its value from vp
- * (vq and vp may be the same)
- */
-struct tbl *
-setint_v(vq, vp)
- register struct tbl *vq, *vp;
-{
- int base;
- long num;
-
- if ((base = getint(vp, &num)) == -1)
- return NULL;
- if (!(vq->flag & INTEGER) && (vq->flag & ALLOC)) {
- vq->flag &= ~ALLOC;
- afree(vq->val.s, vq->areap);
- }
- vq->val.i = num;
- if (vq->type == 0) /* default base */
- vq->type = base;
- vq->flag |= ISSET|INTEGER;
- if (vq->flag&SPECIAL)
- setspec(vq);
- return vq;
-}
-
-static char *
-formatstr(vp, s)
- struct tbl *vp;
- const char *s;
-{
- int olen, nlen;
- char *p, *q;
-
- olen = strlen(s);
-
- if (vp->flag & (RJUST|LJUST)) {
- if (!vp->u2.field) /* default field width */
- vp->u2.field = olen;
- nlen = vp->u2.field;
- } else
- nlen = olen;
-
- p = (char *) alloc(nlen + 1, ATEMP);
- if (vp->flag & (RJUST|LJUST)) {
- int slen;
-
- if (vp->flag & RJUST) {
- const char *q = s + olen;
- /* strip trailing spaces (at&t ksh uses q[-1] == ' ') */
- while (q > s && isspace(q[-1]))
- --q;
- slen = q - s;
- if (slen > vp->u2.field) {
- s += slen - vp->u2.field;
- slen = vp->u2.field;
- }
- shf_snprintf(p, nlen + 1,
- ((vp->flag & ZEROFIL) && digit(*s)) ?
- "%0*s%.*s" : "%*s%.*s",
- vp->u2.field - slen, null, slen, s);
- } else {
- /* strip leading spaces/zeros */
- while (isspace(*s))
- s++;
- if (vp->flag & ZEROFIL)
- while (*s == '0')
- s++;
- shf_snprintf(p, nlen + 1, "%-*.*s",
- vp->u2.field, vp->u2.field, s);
- }
- } else
- memcpy(p, s, olen + 1);
-
- if (vp->flag & UCASEV_AL) {
- for (q = p; *q; q++)
- if (islower(*q))
- *q = toupper(*q);
- } else if (vp->flag & LCASEV) {
- for (q = p; *q; q++)
- if (isupper(*q))
- *q = tolower(*q);
- }
-
- return p;
-}
-
-/*
- * make vp->val.s be "name=value" for quick exporting.
- */
-static void
-export(vp, val)
- register struct tbl *vp;
- const char *val;
-{
- register char *xp;
- char *op = (vp->flag&ALLOC) ? vp->val.s : NULL;
- int namelen = strlen(vp->name);
- int vallen = strlen(val) + 1;
-
- vp->flag |= ALLOC;
- xp = (char*)alloc(namelen + 1 + vallen, vp->areap);
- memcpy(vp->val.s = xp, vp->name, namelen);
- xp += namelen;
- *xp++ = '=';
- vp->type = xp - vp->val.s; /* offset to value */
- memcpy(xp, val, vallen);
- if (op != NULL)
- afree((void*)op, vp->areap);
-}
-
-/*
- * lookup variable (according to (set&LOCAL)),
- * set its attributes (INTEGER, RDONLY, EXPORT, TRACE, LJUST, RJUST, ZEROFIL,
- * LCASEV, UCASEV_AL), and optionally set its value if an assignment.
- */
-struct tbl *
-typeset(var, set, clr, field, base)
- register const char *var;
- Tflag clr, set;
- int field, base;
-{
- register struct tbl *vp;
- struct tbl *vpbase, *t;
- char *tvar;
- const char *val;
-
- /* check for valid variable name, search for value */
- val = skip_varname(var, FALSE);
- if (val == var)
- return NULL;
- if (*val == '[') {
- int len;
-
- len = array_ref_len(val);
- if (len == 0)
- return NULL;
- /* IMPORT is only used when the shell starts up and is
- * setting up its environment. Allow only simple array
- * references at this time since parameter/command substitution
- * is preformed on the [expression], which would be a major
- * security hole.
- */
- if (set & IMPORT) {
- int i;
- for (i = 1; i < len - 1; i++)
- if (!digit(val[i]))
- return NULL;
- }
- val += len;
- }
- if (*val == '=')
- tvar = str_nsave(var, val++ - var, ATEMP);
- else {
- /* Importing from original envirnment: must have an = */
- if (set & IMPORT)
- return NULL;
- tvar = (char *) var;
- val = NULL;
- }
-
- /* Prevent typeset from creating a local PATH/ENV/SHELL */
- if (Flag(FRESTRICTED) && (strcmp(tvar, "PATH") == 0
- || strcmp(tvar, "ENV") == 0
- || strcmp(tvar, "SHELL") == 0))
- errorf("%s: restricted", tvar);
-
- vp = (set&LOCAL) ? local(tvar, (set & LOCAL_COPY) ? TRUE : FALSE)
- : global(tvar);
- set &= ~(LOCAL|LOCAL_COPY);
-
- vpbase = (vp->flag & ARRAY) ? global(arrayname(var)) : vp;
-
- /* only allow export flag to be set. at&t ksh allows any attribute to
- * be changed, which means it can be truncated or modified
- * (-L/-R/-Z/-i).
- */
- if ((vpbase->flag&RDONLY)
- && (val || clr || (set & ~EXPORT)))
- /* XXX check calls - is error here ok by POSIX? */
- errorf("%s: is read only", tvar);
- if (val)
- afree(tvar, ATEMP);
-
- /* most calls are with set/clr == 0 */
- if (set | clr) {
- /* XXX if x[0] isn't set, there will be problems: need to have
- * one copy of attributes for arrays...
- */
- for (t = vpbase; t; t = t->u.array) {
- int fake_assign;
- char UNINITIALIZED(*s);
- char UNINITIALIZED(*free_me);
-
- fake_assign = (t->flag & ISSET) && (!val || t != vp)
- && ((set & (UCASEV_AL|LCASEV|LJUST|RJUST|ZEROFIL))
- || ((t->flag & INTEGER) && (clr & INTEGER))
- || (!(t->flag & INTEGER) && (set & INTEGER)));
- if (fake_assign) {
- if (t->flag & INTEGER) {
- s = str_val(t);
- free_me = (char *) 0;
- } else {
- s = t->val.s + t->type;
- free_me = (t->flag & ALLOC) ? t->val.s
- : (char *) 0;
- }
- t->flag &= ~ALLOC;
- }
- if (!(t->flag & INTEGER) && (set & INTEGER)) {
- t->type = 0;
- t->flag &= ~ALLOC;
- }
- t->flag = (t->flag | set) & ~clr;
- /* Don't change base if assignment is to be done,
- * in case assignment fails.
- */
- if ((set & INTEGER) && base > 0 && (!val || t != vp))
- t->type = base;
- if (set & (LJUST|RJUST|ZEROFIL))
- t->u2.field = field;
- if (fake_assign) {
- setstr(t, s);
- if (free_me)
- afree((void *) free_me, t->areap);
- }
- }
- }
-
- if (val != NULL) {
- if (vp->flag&INTEGER) {
- /* do not zero base before assignment */
- setstr(vp, val);
- /* Done after assignment to override default */
- if (base > 0)
- vp->type = base;
- } else
- setstr(vp, val);
- }
-
- /* only x[0] is ever exported, so use vpbase */
- if ((vpbase->flag&EXPORT) && !(vpbase->flag&INTEGER)
- && vpbase->type == 0)
- export(vpbase, (vpbase->flag&ISSET) ? vpbase->val.s : null);
-
- return vp;
-}
-
-/* Unset a variable. array_ref is set if there was an array reference in
- * the name lookup (eg, x[2]).
- */
-void
-unset(vp, array_ref)
- register struct tbl *vp;
- int array_ref;
-{
- if (vp->flag & ALLOC)
- afree((void*)vp->val.s, vp->areap);
- if ((vp->flag & ARRAY) && !array_ref) {
- struct tbl *a, *tmp;
-
- /* Free up entire array */
- for (a = vp->u.array; a; ) {
- tmp = a;
- a = a->u.array;
- if (tmp->flag & ALLOC)
- afree((void *) tmp->val.s, tmp->areap);
- afree(tmp, tmp->areap);
- }
- vp->u.array = (struct tbl *) 0;
- }
- /* If foo[0] is being unset, the remainder of the array is kept... */
- vp->flag &= SPECIAL | (array_ref ? ARRAY|DEFINED : 0);
- if (vp->flag & SPECIAL)
- unsetspec(vp); /* responsible for `unspecial'ing var */
-}
-
-/* return a pointer to the first char past a legal variable name (returns the
- * argument if there is no legal name, returns * a pointer to the terminating
- * null if whole string is legal).
- */
-char *
-skip_varname(s, aok)
- const char *s;
- int aok;
-{
- int alen;
-
- if (s && letter(*s)) {
- while (*++s && letnum(*s))
- ;
- if (aok && *s == '[' && (alen = array_ref_len(s)))
- s += alen;
- }
- return (char *) s;
-}
-
-/* Return a pointer to the first character past any legal variable name. */
-char *
-skip_wdvarname(s, aok)
- const char *s;
- int aok; /* skip array de-reference? */
-{
- if (s[0] == CHAR && letter(s[1])) {
- do
- s += 2;
- while (s[0] == CHAR && letnum(s[1]));
- if (aok && s[0] == CHAR && s[1] == '[') {
- /* skip possible array de-reference */
- const char *p = s;
- char c;
- int depth = 0;
-
- while (1) {
- if (p[0] != CHAR)
- break;
- c = p[1];
- p += 2;
- if (c == '[')
- depth++;
- else if (c == ']' && --depth == 0) {
- s = p;
- break;
- }
- }
- }
- }
- return (char *) s;
-}
-
-/* Check if coded string s is a variable name */
-int
-is_wdvarname(s, aok)
- const char *s;
- int aok;
-{
- char *p = skip_wdvarname(s, aok);
-
- return p != s && p[0] == EOS;
-}
-
-/* Check if coded string s is a variable assignment */
-int
-is_wdvarassign(s)
- const char *s;
-{
- char *p = skip_wdvarname(s, TRUE);
-
- return p != s && p[0] == CHAR && p[1] == '=';
-}
-
-/*
- * Make the exported environment from the exported names in the dictionary.
- */
-char **
-makenv()
-{
- struct block *l = e->loc;
- XPtrV env;
- register struct tbl *vp, **vpp;
- register int i;
-
- XPinit(env, 64);
- for (l = e->loc; l != NULL; l = l->next)
- for (vpp = l->vars.tbls, i = l->vars.size; --i >= 0; )
- if ((vp = *vpp++) != NULL
- && (vp->flag&(ISSET|EXPORT)) == (ISSET|EXPORT)) {
- register struct block *l2;
- register struct tbl *vp2;
- unsigned h = hash(vp->name);
-
- /* unexport any redefined instances */
- for (l2 = l->next; l2 != NULL; l2 = l2->next) {
- vp2 = tsearch(&l2->vars, vp->name, h);
- if (vp2 != NULL)
- vp2->flag &= ~EXPORT;
- }
- if ((vp->flag&INTEGER)) {
- /* integer to string */
- char *val;
- val = str_val(vp);
- vp->flag &= ~INTEGER;
- setstr(vp, val);
- }
- XPput(env, vp->val.s);
- }
- XPput(env, NULL);
- return (char **) XPclose(env);
-}
-
-/*
- * handle special variables with side effects - PATH, SECONDS.
- */
-
-/* Test if name is a special parameter */
-static int
-special(name)
- register const char * name;
-{
- register struct tbl *tp;
-
- tp = tsearch(&specials, name, hash(name));
- return tp ? tp->type : V_NONE;
-}
-
-#ifdef KSH
-static time_t seconds; /* time SECONDS last set */
-#endif /* KSH */
-
-static void
-getspec(vp)
- register struct tbl *vp;
-{
- switch (special(vp->name)) {
-#ifdef KSH
- case V_SECONDS:
- vp->flag &= ~SPECIAL;
- setint(vp, (long) (time((time_t *)0) - seconds));
- vp->flag |= SPECIAL;
- break;
- case V_RANDOM:
- vp->flag &= ~SPECIAL;
- setint(vp, (long) (rand() & 0x7fff));
- vp->flag |= SPECIAL;
- break;
-#endif /* KSH */
-#ifdef HISTORY
- case V_HISTSIZE:
- vp->flag &= ~SPECIAL;
- setint(vp, (long) histsize);
- vp->flag |= SPECIAL;
- break;
-#endif /* HISTORY */
- }
-}
-
-static void
-setspec(vp)
- register struct tbl *vp;
-{
- char *s;
-
- switch (special(vp->name)) {
- case V_PATH:
- path = str_val(vp);
- flushcom(1); /* clear tracked aliases */
- break;
- case V_IFS:
- setctypes(s = str_val(vp), C_IFS);
- ifs0 = *s;
- break;
- case V_OPTIND:
- getopts_reset((int) intval(vp));
- break;
- case V_POSIXLY_CORRECT:
- change_flag(FPOSIX, OF_SPECIAL, 1);
- break;
- case V_TMPDIR:
- if (tmpdir) {
- afree(tmpdir, APERM);
- tmpdir = (char *) 0;
- }
- /* Use tmpdir iff it is an absolute path, is writable and
- * searchable and is a directory...
- */
- {
- struct stat statb;
- s = str_val(vp);
- if (ISABSPATH(s) && eaccess(s, W_OK|X_OK) == 0
- && stat(s, &statb) == 0 && S_ISDIR(statb.st_mode))
- tmpdir = str_save(s, APERM);
- }
- break;
-#ifdef HISTORY
- case V_HISTSIZE:
- vp->flag &= ~SPECIAL;
- sethistsize((int) intval(vp));
- vp->flag |= SPECIAL;
- break;
- case V_HISTFILE:
- sethistfile(str_val(vp));
- break;
-#endif /* HISTORY */
-#ifdef EDIT
- case V_VISUAL:
- set_editmode(str_val(vp));
- break;
- case V_EDITOR:
- if (!(global("VISUAL")->flag & ISSET))
- set_editmode(str_val(vp));
- break;
- case V_COLUMNS:
- if ((x_cols = intval(vp)) <= MIN_COLS)
- x_cols = MIN_COLS;
- break;
-#endif /* EDIT */
-#ifdef KSH
- case V_MAIL:
- mbset(str_val(vp));
- break;
- case V_MAILPATH:
- mpset(str_val(vp));
- break;
- case V_MAILCHECK:
- /* mail_check_set(intval(vp)); */
- break;
- case V_RANDOM:
- vp->flag &= ~SPECIAL;
- srand((unsigned int)intval(vp));
- vp->flag |= SPECIAL;
- break;
- case V_SECONDS:
- vp->flag &= ~SPECIAL;
- seconds = time((time_t*) 0) - intval(vp);
- vp->flag |= SPECIAL;
- break;
- case V_TMOUT:
- /* at&t ksh seems to do this (only listen if integer) */
- if (vp->flag & INTEGER)
- ksh_tmout = vp->val.i >= 0 ? vp->val.i : 0;
- break;
-#endif /* KSH */
- }
-}
-
-static void
-unsetspec(vp)
- register struct tbl *vp;
-{
- switch (special(vp->name)) {
- case V_PATH:
- path = def_path;
- flushcom(1); /* clear tracked aliases */
- break;
- case V_IFS:
- setctypes(" \t\n", C_IFS);
- ifs0 = ' ';
- break;
- case V_TMPDIR:
- /* should not become unspecial */
- if (tmpdir) {
- afree(tmpdir, APERM);
- tmpdir = (char *) 0;
- }
- break;
-#ifdef KSH
- case V_MAIL:
- mbset((char *) 0);
- break;
- case V_MAILPATH:
- mpset((char *) 0);
- break;
- case V_TMOUT:
- /* at&t ksh doesn't do this. TMOUT becomes unspecial so
- * future assignments don't have effect. Could be
- * useful (eg, after "TMOUT=60; unset TMOUT", user
- * can't get rid of the timeout...). Should be handled
- * by generic unset code...
- */
- ksh_tmout = 0;
- break;
-#endif /* KSH */
- /* todo: generic action for specials (at&t says variables
- * lose their special meaning when unset but global() checks
- * the name of new vars to see if they are special)
- * lose meaning: _, ERRNO, LINENO, MAILCHECK,
- * OPTARG, OPTIND, RANDOM, SECONDS, TMOUT.
- * unknown: MAIL, MAILPATH, HISTSIZE, HISTFILE,
- * no effect: IFS, COLUMNS, PATH, TMPDIR,
- * VISUAL, EDITOR,
- * POSIXLY_CORRECT (use set +o posix instead)
- */
- }
-}
-
-/*
- * Search for (and possibly create) a table entry starting with
- * vp, indexed by val.
- */
-static struct tbl *
-arraysearch(vp, val)
- struct tbl *vp;
- int val;
-{
- struct tbl *prev, *curr, *new;
-
- vp->flag |= ARRAY|DEFINED;
-
- /* The table entry is always [0] */
- if (val == 0) {
- vp->index = 0;
- return vp;
- }
- prev = vp;
- curr = vp->u.array;
- while (curr && curr->index < val) {
- prev = curr;
- curr = curr->u.array;
- }
- if (curr && curr->index == val) {
- if (curr->flag&ISSET)
- return curr;
- else
- new = curr;
- } else
- new = (struct tbl *)alloc(sizeof(struct tbl)+strlen(vp->name)+1, vp->areap);
- strcpy(new->name, vp->name);
- new->flag = vp->flag & ~(ALLOC|DEFINED|ISSET|SPECIAL);
- new->type = vp->type;
- new->areap = vp->areap;
- new->u2.field = vp->u2.field;
- new->index = val;
- if (curr != new) { /* not reusing old array entry */
- prev->u.array = new;
- new->u.array = curr;
- }
- return new;
-}
-
-/* Return the length of an array reference (eg, [1+2]) - cp is assumed
- * to point to the open bracket. Returns 0 if there is no matching closing
- * bracket.
- */
-int
-array_ref_len(cp)
- const char *cp;
-{
- const char *s = cp;
- int c;
- int depth = 0;
-
- while ((c = *s++) && (c != ']' || --depth))
- if (c == '[')
- depth++;
- if (!c)
- return 0;
- return s - cp;
-}
-
-/*
- * Make a copy of the base of an array name
- */
-char *
-arrayname(str)
- const char *str;
-{
- const char *p;
-
- if ((p = strchr(str, '[')) == 0)
- /* Shouldn't happen, but why worry? */
- return (char *) str;
-
- return str_nsave(str, p - str, ATEMP);
-}
-
-/* Set (or overwrite, if !reset) the array variable var to the values in vals.
- */
-void
-set_array(var, reset, vals)
- const char *var;
- int reset;
- char **vals;
-{
- struct tbl *vp, *vq;
- int i;
-
- /* to get local array, use "typeset foo; set -A foo" */
- vp = global(var);
-
- /* Note: at&t ksh allows set -A but not set +A of a read-only var */
- if ((vp->flag&RDONLY))
- errorf("%s: is read only", var);
- /* This code is quite non-optimal */
- if (reset > 0)
- /* trash existing values and attributes */
- unset(vp, 0);
- /* todo: would be nice for assignment to completely succeed or
- * completely fail. Only really effects integer arrays:
- * evaluation of some of vals[] may fail...
- */
- for (i = 0; vals[i]; i++) {
- vq = arraysearch(vp, i);
- setstr(vq, vals[i]);
- }
-}
diff --git a/bin/pdksh/version.c b/bin/pdksh/version.c
deleted file mode 100644
index 54394213105..00000000000
--- a/bin/pdksh/version.c
+++ /dev/null
@@ -1,10 +0,0 @@
-/* $OpenBSD: version.c,v 1.5 1996/11/21 07:59:37 downsj Exp $ */
-
-/*
- * value of $KSH_VERSION (or $SH_VERSION)
- */
-
-#include "sh.h"
-
-const char ksh_version [] =
- "@(#)PD KSH v5.2.12 96/10/29";
diff --git a/bin/pdksh/vi.c b/bin/pdksh/vi.c
deleted file mode 100644
index 81950b224a3..00000000000
--- a/bin/pdksh/vi.c
+++ /dev/null
@@ -1,2174 +0,0 @@
-/* $OpenBSD: vi.c,v 1.5 1997/06/19 13:58:49 kstailey Exp $ */
-
-/*
- * vi command editing
- * written by John Rochester (initially for nsh)
- * bludgeoned to fit pdksh by Larry Bouzane, Jeff Sparkes & Eric Gisin
- *
- */
-#include "config.h"
-#ifdef VI
-
-#include "sh.h"
-#include <ctype.h>
-#include "ksh_stat.h" /* completion */
-#include "edit.h"
-
-#define CMDLEN 1024
-#define Ctrl(c) (c&0x1f)
-#define is_wordch(c) (letnum(c))
-
-struct edstate {
- int winleft;
- char *cbuf;
- int cbufsize;
- int linelen;
- int cursor;
-};
-
-
-static int vi_hook ARGS((int ch));
-static void vi_reset ARGS((char *buf, size_t len));
-static int nextstate ARGS((int ch));
-static int vi_insert ARGS((int ch));
-static int vi_cmd ARGS((int argcnt, const char *cmd));
-static int domove ARGS((int argcnt, const char *cmd, int sub));
-static int redo_insert ARGS((int count));
-static void yank_range ARGS((int a, int b));
-static int bracktype ARGS((int ch));
-static void save_cbuf ARGS((void));
-static void restore_cbuf ARGS((void));
-static void edit_reset ARGS((char *buf, size_t len));
-static int putbuf ARGS((const char *buf, int len, int repl));
-static void del_range ARGS((int a, int b));
-static int findch ARGS((int ch, int cnt, int forw, int incl));
-static int forwword ARGS((int argcnt));
-static int backword ARGS((int argcnt));
-static int endword ARGS((int argcnt));
-static int Forwword ARGS((int argcnt));
-static int Backword ARGS((int argcnt));
-static int Endword ARGS((int argcnt));
-static int grabhist ARGS((int save, int n));
-static int grabsearch ARGS((int save, int start, int fwd, char *pat));
-static void redraw_line ARGS((int newline));
-static void refresh ARGS((int leftside));
-static int outofwin ARGS((void));
-static void rewindow ARGS((void));
-static int newcol ARGS((int ch, int col));
-static void display ARGS((char *wb1, char *wb2, int leftside));
-static void ed_mov_opt ARGS((int col, char *wb));
-static int expand_word ARGS((int command));
-static int complete_word ARGS((int command, int count));
-static int print_expansions ARGS((struct edstate *e, int command));
-static int char_len ARGS((int c));
-static void x_vi_zotc ARGS((int c));
-static void vi_pprompt ARGS((int full));
-static void vi_error ARGS((void));
-static void vi_macro_reset ARGS((void));
-
-#define C_ 0x1 /* a valid command that isn't a M_, E_, U_ */
-#define M_ 0x2 /* movement command (h, l, etc.) */
-#define E_ 0x4 /* extended command (c, d, y) */
-#define X_ 0x8 /* long command (@, f, F, t, T, etc.) */
-#define U_ 0x10 /* an UN-undoable command (that isn't a M_) */
-#define B_ 0x20 /* bad command (^@) */
-#define Z_ 0x40 /* repeat count defaults to 0 (not 1) */
-#define S_ 0x80 /* search (/, ?) */
-
-#define is_bad(c) (classify[(c)&0x7f]&B_)
-#define is_cmd(c) (classify[(c)&0x7f]&(M_|E_|C_|U_))
-#define is_move(c) (classify[(c)&0x7f]&M_)
-#define is_extend(c) (classify[(c)&0x7f]&E_)
-#define is_long(c) (classify[(c)&0x7f]&X_)
-#define is_undoable(c) (!(classify[(c)&0x7f]&U_))
-#define is_srch(c) (classify[(c)&0x7f]&S_)
-#define is_zerocount(c) (classify[(c)&0x7f]&Z_)
-
-const unsigned char classify[128] = {
- /* 0 1 2 3 4 5 6 7 */
- /* 0 ^@ ^A ^B ^C ^D ^E ^F ^G */
- B_, 0, 0, 0, 0, C_|U_, C_|Z_, 0,
- /* 01 ^H ^I ^J ^K ^L ^M ^N ^O */
- M_, C_|Z_, 0, 0, C_|U_, 0, C_, 0,
- /* 02 ^P ^Q ^R ^S ^T ^U ^V ^W */
- C_, 0, C_|U_, 0, 0, 0, C_, 0,
- /* 03 ^X ^Y ^Z ^[ ^\ ^] ^^ ^_ */
- C_, 0, 0, C_|Z_, 0, 0, 0, 0,
- /* 04 <space> ! " # $ % & ' */
- M_, 0, 0, C_, M_, M_, 0, 0,
- /* 05 ( ) * + , - . / */
- 0, 0, C_, C_, M_, C_, 0, C_|S_,
- /* 06 0 1 2 3 4 5 6 7 */
- M_, 0, 0, 0, 0, 0, 0, 0,
- /* 07 8 9 : ; < = > ? */
- 0, 0, 0, M_, 0, C_, 0, C_|S_,
- /* 010 @ A B C D E F G */
- C_|X_, C_, M_, C_, C_, M_, M_|X_, C_|U_|Z_,
- /* 011 H I J K L M N O */
- 0, C_, 0, 0, 0, 0, C_|U_, 0,
- /* 012 P Q R S T U V W */
- C_, 0, C_, C_, M_|X_, C_, 0, M_,
- /* 013 X Y Z [ \ ] ^ _ */
- C_, C_|U_, 0, 0, C_|Z_, 0, M_, C_|Z_,
- /* 014 ` a b c d e f g */
- 0, C_, M_, E_, E_, M_, M_|X_, C_|Z_,
- /* 015 h i j k l m n o */
- M_, C_, C_|U_, C_|U_, M_, 0, C_|U_, 0,
- /* 016 p q r s t u v w */
- C_, 0, X_, C_, M_|X_, C_|U_, C_|U_|Z_,M_,
- /* 017 x y z { | } ~ ^? */
- C_, E_|U_, 0, 0, M_|Z_, 0, C_, 0
-};
-
-#define MAXVICMD 3
-#define SRCHLEN 40
-
-#define INSERT 1
-#define REPLACE 2
-
-#define VNORMAL 0 /* command, insert or replace mode */
-#define VARG1 1 /* digit prefix (first, eg, 5l) */
-#define VEXTCMD 2 /* cmd + movement (eg, cl) */
-#define VARG2 3 /* digit prefix (second, eg, 2c3l) */
-#define VXCH 4 /* f, F, t, T, @ */
-#define VFAIL 5 /* bad command */
-#define VCMD 6 /* single char command (eg, X) */
-#define VREDO 7 /* . */
-#define VLIT 8 /* ^V */
-#define VSEARCH 9 /* /, ? */
-#define VVERSION 10 /* <ESC> ^V */
-
-static char undocbuf[CMDLEN];
-
-static struct edstate *save_edstate ARGS((struct edstate *old));
-static void restore_edstate ARGS((struct edstate *old, struct edstate *new));
-static void free_edstate ARGS((struct edstate *old));
-
-static struct edstate ebuf;
-static struct edstate undobuf = { 0, undocbuf, CMDLEN, 0, 0 };
-
-static struct edstate *es; /* current editor state */
-static struct edstate *undo;
-
-static char ibuf[CMDLEN]; /* input buffer */
-static int first_insert; /* set when starting in insert mode */
-static int saved_inslen; /* saved inslen for first insert */
-static int inslen; /* length of input buffer */
-static int srchlen; /* length of current search pattern */
-static char ybuf[CMDLEN]; /* yank buffer */
-static int yanklen; /* length of yank buffer */
-static int fsavecmd = ' '; /* last find command */
-static int fsavech; /* character to find */
-static char lastcmd[MAXVICMD]; /* last non-move command */
-static int lastac; /* argcnt for lastcmd */
-static int lastsearch = ' '; /* last search command */
-static char srchpat[SRCHLEN]; /* last search pattern */
-static int insert; /* non-zero in insert mode */
-static int hnum; /* position in history */
-static int ohnum; /* history line copied (after mod) */
-static int hlast; /* 1 past last position in history */
-static int modified; /* buffer has been "modified" */
-static int state;
-
-/* Information for keeping track of macros that are being expanded.
- * The format of buf is the alias contents followed by a null byte followed
- * by the name (letter) of the alias. The end of the buffer is marked by
- * a double null. The name of the alias is stored so recursive macros can
- * be detected.
- */
-struct macro_state {
- unsigned char *p; /* current position in buf */
- unsigned char *buf; /* pointer to macro(s) being expanded */
- int len; /* how much data in buffer */
-};
-static struct macro_state macro;
-
-enum expand_mode { NONE, EXPAND, COMPLETE, PRINT };
-static enum expand_mode expanded = NONE;/* last input was expanded */
-
-int
-x_vi(buf, len)
- char *buf;
- size_t len;
-{
- int c;
-
- vi_reset(buf, len > CMDLEN ? CMDLEN : len);
- vi_pprompt(1);
- x_flush();
- while (1) {
- if (macro.p) {
- c = *macro.p++;
- /* end of current macro? */
- if (!c) {
- /* more macros left to finish? */
- if (*macro.p++)
- continue;
- /* must be the end of all the macros */
- vi_macro_reset();
- c = x_getc();
- }
- } else
- c = x_getc();
- if (c == -1)
- break;
- if (state != VLIT) {
- if (c == edchars.intr || c == edchars.quit) {
- /* pretend we got an interrupt */
- x_vi_zotc(c);
- x_flush();
- trapsig(c == edchars.intr ? SIGINT : SIGQUIT);
- x_mode(FALSE);
- unwind(LSHELL);
- } else if (c == edchars.eof && state != VVERSION) {
- if (es->linelen == 0) {
- x_vi_zotc(edchars.eof);
- c = -1;
- break;
- }
- continue;
- }
- }
- if (vi_hook(c))
- break;
- x_flush();
- }
-
- x_putc('\r'); x_putc('\n'); x_flush();
-
- if (c == -1)
- return -1;
-
- if (es->cbuf != buf)
- memmove(buf, es->cbuf, es->linelen);
-
- buf[es->linelen++] = '\n';
-
- return es->linelen;
-}
-
-static int
-vi_hook(ch)
- int ch;
-{
- static char curcmd[MAXVICMD];
- static char locpat[SRCHLEN];
- static int cmdlen;
- static int argc1, argc2;
-
- switch (state) {
-
- case VNORMAL:
- if (insert != 0) {
- if (ch == Ctrl('v')) {
- state = VLIT;
- ch = '^';
- }
- switch (vi_insert(ch)) {
- case -1:
-#ifdef OS2
- /* Arrow keys generate 0xe0X, where X is H.. */
- state = VCMD;
- argc1 = 1;
- switch (x_getc()) {
- case 'H':
- *curcmd='k';
- break;
- case 'K':
- *curcmd='h';
- break;
- case 'P':
- *curcmd='j';
- break;
- case 'M':
- *curcmd='l';
- break;
- default:
- vi_error();
- state = VNORMAL;
- }
- break;
-#else /* OS2 */
- vi_error();
- state = VNORMAL;
-#endif /* OS2 */
- break;
- case 0:
- if (state == VLIT) {
- es->cursor--;
- refresh(0);
- } else
- refresh(insert != 0);
- break;
- case 1:
- return 1;
- }
- } else {
- if (ch == '\r' || ch == '\n')
- return 1;
- cmdlen = 0;
- argc1 = 0;
- if (ch >= '1' && ch <= '9') {
- argc1 = ch - '0';
- state = VARG1;
- } else {
- curcmd[cmdlen++] = ch;
- state = nextstate(ch);
- if (state == VSEARCH) {
- save_cbuf();
- es->cursor = 0;
- es->linelen = 0;
- if (ch == '/') {
- if (putbuf("/", 1, 0) != 0) {
- return -1;
- }
- } else if (putbuf("?", 1, 0) != 0)
- return -1;
- refresh(0);
- }
- if (state == VVERSION) {
- save_cbuf();
- es->cursor = 0;
- es->linelen = 0;
- putbuf(ksh_version + 4,
- strlen(ksh_version + 4), 0);
- refresh(0);
- }
- }
- }
- break;
-
- case VLIT:
- if (is_bad(ch)) {
- del_range(es->cursor, es->cursor + 1);
- vi_error();
- } else
- es->cbuf[es->cursor++] = ch;
- refresh(1);
- state = VNORMAL;
- break;
-
- case VVERSION:
- restore_cbuf();
- state = VNORMAL;
- refresh(0);
- break;
-
- case VARG1:
- if (isdigit(ch))
- argc1 = argc1 * 10 + ch - '0';
- else {
- curcmd[cmdlen++] = ch;
- state = nextstate(ch);
- }
- break;
-
- case VEXTCMD:
- argc2 = 0;
- if (ch >= '1' && ch <= '9') {
- argc2 = ch - '0';
- state = VARG2;
- return 0;
- } else {
- curcmd[cmdlen++] = ch;
- if (ch == curcmd[0])
- state = VCMD;
- else if (is_move(ch))
- state = nextstate(ch);
- else
- state = VFAIL;
- }
- break;
-
- case VARG2:
- if (isdigit(ch))
- argc2 = argc2 * 10 + ch - '0';
- else {
- if (argc1 == 0)
- argc1 = argc2;
- else
- argc1 *= argc2;
- curcmd[cmdlen++] = ch;
- if (ch == curcmd[0])
- state = VCMD;
- else if (is_move(ch))
- state = nextstate(ch);
- else
- state = VFAIL;
- }
- break;
-
- case VXCH:
- if (ch == Ctrl('['))
- state = VNORMAL;
- else {
- curcmd[cmdlen++] = ch;
- state = VCMD;
- }
- break;
-
- case VSEARCH:
- if (ch == '\r' || ch == '\n' /*|| ch == Ctrl('[')*/ ) {
- restore_cbuf();
- /* Repeat last search? */
- if (srchlen == 0) {
- if (!srchpat[0]) {
- vi_error();
- state = VNORMAL;
- refresh(0);
- return 0;
- }
- } else {
- locpat[srchlen] = '\0';
- (void) strcpy(srchpat, locpat);
- }
- state = VCMD;
- } else if (ch == edchars.erase || ch == Ctrl('h')) {
- if (srchlen != 0) {
- srchlen--;
- es->linelen -= char_len((unsigned char) locpat[srchlen]);
- es->cursor = es->linelen;
- refresh(0);
- return 0;
- }
- restore_cbuf();
- state = VNORMAL;
- refresh(0);
- } else if (ch == edchars.kill) {
- srchlen = 0;
- es->linelen = 1;
- es->cursor = 1;
- refresh(0);
- return 0;
- } else if (ch == edchars.werase) {
- int i;
- int n = srchlen;
-
- while (n > 0 && isspace(locpat[n - 1]))
- n--;
- while (n > 0 && !isspace(locpat[n - 1]))
- n--;
- for (i = srchlen; --i >= n; )
- es->linelen -= char_len((unsigned char) locpat[i]);
- srchlen = n;
- es->cursor = es->linelen;
- refresh(0);
- return 0;
- } else {
- if (srchlen == SRCHLEN - 1)
- vi_error();
- else {
- locpat[srchlen++] = ch;
- if ((ch & 0x80) && Flag(FVISHOW8)) {
- es->cbuf[es->linelen++] = 'M';
- es->cbuf[es->linelen++] = '-';
- ch &= 0x7f;
- }
- if (ch < ' ' || ch == 0x7f) {
- es->cbuf[es->linelen++] = '^';
- es->cbuf[es->linelen++] = ch ^ '@';
- } else
- es->cbuf[es->linelen++] = ch;
- es->cursor = es->linelen;
- refresh(0);
- }
- return 0;
- }
- break;
- }
-
- switch (state) {
- case VCMD:
- state = VNORMAL;
- switch (vi_cmd(argc1, curcmd)) {
- case -1:
- vi_error();
- refresh(0);
- break;
- case 0:
- if (insert != 0)
- inslen = 0;
- refresh(insert != 0);
- break;
- case 1:
- refresh(0);
- return 1;
- case 2:
- /* back from a 'v' command - don't redraw the screen */
- return 1;
- }
- break;
-
- case VREDO:
- state = VNORMAL;
- if (argc1 != 0)
- lastac = argc1;
- switch (vi_cmd(lastac, lastcmd) != 0) {
- case -1:
- vi_error();
- refresh(0);
- break;
- case 0:
- if (insert != 0) {
- if (lastcmd[0] == 's' || lastcmd[0] == 'c' ||
- lastcmd[0] == 'C') {
- if (redo_insert(1) != 0)
- vi_error();
- } else {
- if (redo_insert(lastac) != 0)
- vi_error();
- }
- }
- refresh(0);
- break;
- case 1:
- refresh(0);
- return 1;
- case 2:
- /* back from a 'v' command - don't redraw the screen */
- return 1;
- }
- break;
-
- case VFAIL:
- state = VNORMAL;
- vi_error();
- break;
- }
- return 0;
-}
-
-static void
-vi_reset(buf, len)
- char *buf;
- size_t len;
-{
- state = VNORMAL;
- ohnum = hnum = hlast = histnum(-1) + 1;
- insert = INSERT;
- saved_inslen = inslen;
- first_insert = 1;
- inslen = 0;
- modified = 1;
- vi_macro_reset();
- edit_reset(buf, len);
-}
-
-static int
-nextstate(ch)
- int ch;
-{
- if (is_extend(ch))
- return VEXTCMD;
- else if (is_srch(ch))
- return VSEARCH;
- else if (is_long(ch))
- return VXCH;
- else if (ch == '.')
- return VREDO;
- else if (ch == Ctrl('v'))
- return VVERSION;
- else if (is_cmd(ch))
- return VCMD;
- else
- return VFAIL;
-}
-
-static int
-vi_insert(ch)
- int ch;
-{
- int tcursor;
-
- if (ch == edchars.erase || ch == Ctrl('h')) {
- if (insert == REPLACE) {
- if (es->cursor == undo->cursor) {
- vi_error();
- return 0;
- }
- if (inslen > 0)
- inslen--;
- es->cursor--;
- if (es->cursor >= undo->linelen)
- es->linelen--;
- else
- es->cbuf[es->cursor] = undo->cbuf[es->cursor];
- } else {
- if (es->cursor == 0) {
- /* x_putc(BEL); no annoying bell here */
- return 0;
- }
- if (inslen > 0)
- inslen--;
- es->cursor--;
- es->linelen--;
- memmove(&es->cbuf[es->cursor], &es->cbuf[es->cursor+1],
- es->linelen - es->cursor + 1);
- }
- expanded = NONE;
- return 0;
- }
- if (ch == edchars.kill) {
- if (es->cursor != 0) {
- inslen = 0;
- memmove(es->cbuf, &es->cbuf[es->cursor],
- es->linelen - es->cursor);
- es->linelen -= es->cursor;
- es->cursor = 0;
- }
- expanded = NONE;
- return 0;
- }
- if (ch == edchars.werase) {
- if (es->cursor != 0) {
- tcursor = Backword(1);
- memmove(&es->cbuf[tcursor], &es->cbuf[es->cursor],
- es->linelen - es->cursor);
- es->linelen -= es->cursor - tcursor;
- if (inslen < es->cursor - tcursor)
- inslen = 0;
- else
- inslen -= es->cursor - tcursor;
- es->cursor = tcursor;
- }
- expanded = NONE;
- return 0;
- }
- /* If any chars are entered before escape, trash the saved insert
- * buffer (if user inserts & deletes char, ibuf gets trashed and
- * we don't want to use it)
- */
- if (first_insert && ch != Ctrl('['))
- saved_inslen = 0;
- switch (ch) {
-
-#ifdef OS2
- case 224: /* function key prefix */
-#endif /* OS2 */
- case '\0':
- return -1;
-
- case '\r':
- case '\n':
- return 1;
-
- case Ctrl('['):
- expanded = NONE;
- if (first_insert) {
- first_insert = 0;
- if (inslen == 0) {
- inslen = saved_inslen;
- return redo_insert(0);
- }
- lastcmd[0] = 'a';
- lastac = 1;
- }
- if (lastcmd[0] == 's' || lastcmd[0] == 'c' ||
- lastcmd[0] == 'C')
- return redo_insert(0);
- else
- return redo_insert(lastac - 1);
-
- /* { Begin nonstandard vi commands */
- case Ctrl('x'):
- expand_word(0);
- break;
-
- case Ctrl('f'):
- complete_word(0, 0);
- break;
-
- case Ctrl('e'):
- print_expansions(es, 0);
- break;
-
- case Ctrl('i'):
- if (Flag(FVITABCOMPLETE)) {
- complete_word(0, 0);
- break;
- }
- /* FALLTHROUGH */
- /* End nonstandard vi commands } */
-
- default:
- if (es->linelen == es->cbufsize - 1)
- return -1;
- ibuf[inslen++] = ch;
- if (insert == INSERT) {
- memmove(&es->cbuf[es->cursor+1], &es->cbuf[es->cursor],
- es->linelen - es->cursor);
- es->linelen++;
- }
- es->cbuf[es->cursor++] = ch;
- if (insert == REPLACE && es->cursor > es->linelen)
- es->linelen++;
- expanded = NONE;
- }
- return 0;
-}
-
-static int
-vi_cmd(argcnt, cmd)
- int argcnt;
- const char *cmd;
-{
- int ncursor;
- int cur, c1, c2, c3 = 0;
- int any;
- struct edstate *t;
-
- if (argcnt == 0 && !is_zerocount(*cmd))
- argcnt = 1;
-
- if (is_move(*cmd)) {
- if ((cur = domove(argcnt, cmd, 0)) >= 0) {
- if (cur == es->linelen && cur != 0)
- cur--;
- es->cursor = cur;
- } else
- return -1;
- } else {
- /* Don't save state in middle of macro.. */
- if (is_undoable(*cmd) && !macro.p) {
- undo->winleft = es->winleft;
- memmove(undo->cbuf, es->cbuf, es->linelen);
- undo->linelen = es->linelen;
- undo->cursor = es->cursor;
- lastac = argcnt;
- memmove(lastcmd, cmd, MAXVICMD);
- }
- switch (*cmd) {
-
- case Ctrl('l'):
- case Ctrl('r'):
- redraw_line(1);
- break;
-
- case '@':
- {
- static char alias[] = "_\0";
- struct tbl *ap;
- int olen, nlen;
- char *p, *nbuf;
-
- /* lookup letter in alias list... */
- alias[1] = cmd[1];
- ap = tsearch(&aliases, alias, hash(alias));
- if (!cmd[1] || !ap || !(ap->flag & ISSET))
- return -1;
- /* check if this is a recursive call... */
- if ((p = (char *) macro.p))
- while ((p = strchr(p, '\0')) && p[1])
- if (*++p == cmd[1])
- return -1;
- /* insert alias into macro buffer */
- nlen = strlen(ap->val.s) + 1;
- olen = !macro.p ? 2
- : macro.len - (macro.p - macro.buf);
- nbuf = alloc(nlen + 1 + olen, APERM);
- memcpy(nbuf, ap->val.s, nlen);
- nbuf[nlen++] = cmd[1];
- if (macro.p) {
- memcpy(nbuf + nlen, macro.p, olen);
- afree(macro.buf, APERM);
- nlen += olen;
- } else {
- nbuf[nlen++] = '\0';
- nbuf[nlen++] = '\0';
- }
- macro.p = macro.buf = (unsigned char *) nbuf;
- macro.len = nlen;
- }
- break;
-
- case 'a':
- modified = 1; hnum = hlast;
- if (es->linelen != 0)
- es->cursor++;
- insert = INSERT;
- break;
-
- case 'A':
- modified = 1; hnum = hlast;
- del_range(0, 0);
- es->cursor = es->linelen;
- insert = INSERT;
- break;
-
- case 'S':
- es->cursor = domove(1, "^", 1);
- del_range(es->cursor, es->linelen);
- modified = 1; hnum = hlast;
- insert = INSERT;
- break;
-
- case 'Y':
- cmd = "y$";
- /* ahhhhhh... */
- case 'c':
- case 'd':
- case 'y':
- if (*cmd == cmd[1]) {
- c1 = *cmd == 'c' ? domove(1, "^", 1) : 0;
- c2 = es->linelen;
- } else if (!is_move(cmd[1]))
- return -1;
- else {
- if ((ncursor = domove(argcnt, &cmd[1], 1)) < 0)
- return -1;
- if (*cmd == 'c' &&
- (cmd[1]=='w' || cmd[1]=='W') &&
- !isspace(es->cbuf[es->cursor])) {
- while (isspace(es->cbuf[--ncursor]))
- ;
- ncursor++;
- }
- if (ncursor > es->cursor) {
- c1 = es->cursor;
- c2 = ncursor;
- } else {
- c1 = ncursor;
- c2 = es->cursor;
- if (cmd[1] == '%')
- c2++;
- }
- }
- if (*cmd != 'c' && c1 != c2)
- yank_range(c1, c2);
- if (*cmd != 'y') {
- del_range(c1, c2);
- es->cursor = c1;
- }
- if (*cmd == 'c') {
- modified = 1; hnum = hlast;
- insert = INSERT;
- }
- break;
-
- case 'p':
- modified = 1; hnum = hlast;
- if (es->linelen != 0)
- es->cursor++;
- while (putbuf(ybuf, yanklen, 0) == 0 && --argcnt > 0)
- ;
- if (es->cursor != 0)
- es->cursor--;
- if (argcnt != 0)
- return -1;
- break;
-
- case 'P':
- modified = 1; hnum = hlast;
- any = 0;
- while (putbuf(ybuf, yanklen, 0) == 0 && --argcnt > 0)
- any = 1;
- if (any && es->cursor != 0)
- es->cursor--;
- if (argcnt != 0)
- return -1;
- break;
-
- case 'C':
- modified = 1; hnum = hlast;
- del_range(es->cursor, es->linelen);
- insert = INSERT;
- break;
-
- case 'D':
- yank_range(es->cursor, es->linelen);
- del_range(es->cursor, es->linelen);
- if (es->cursor != 0)
- es->cursor--;
- break;
-
- case 'g':
- if (!argcnt)
- argcnt = hlast + 1;
- /* fall through */
- case 'G':
- if (!argcnt)
- argcnt = 1;
- else
- argcnt = hlast - (source->line - argcnt);
- if (grabhist(modified, argcnt - 1) < 0)
- return -1;
- else {
- modified = 0;
- hnum = argcnt - 1;
- }
- break;
-
- case 'i':
- modified = 1; hnum = hlast;
- insert = INSERT;
- break;
-
- case 'I':
- modified = 1; hnum = hlast;
- es->cursor = domove(1, "^", 1);
- insert = INSERT;
- break;
-
- case 'j':
- case '+':
- case Ctrl('n'):
- if (grabhist(modified, hnum + argcnt) < 0)
- return -1;
- else {
- modified = 0;
- hnum += argcnt;
- }
- break;
-
- case 'k':
- case '-':
- case Ctrl('p'):
- if (grabhist(modified, hnum - argcnt) < 0)
- return -1;
- else {
- modified = 0;
- hnum -= argcnt;
- }
- break;
-
- case 'r':
- if (es->linelen == 0)
- return -1;
- modified = 1; hnum = hlast;
- if (cmd[1] == 0)
- vi_error();
- else
- es->cbuf[es->cursor] = cmd[1];
- break;
-
- case 'R':
- modified = 1; hnum = hlast;
- insert = REPLACE;
- break;
-
- case 's':
- if (es->linelen == 0)
- return -1;
- modified = 1; hnum = hlast;
- if (es->cursor + argcnt > es->linelen)
- argcnt = es->linelen - es->cursor;
- del_range(es->cursor, es->cursor + argcnt);
- insert = INSERT;
- break;
-
- case 'v':
- if (es->linelen == 0)
- return -1;
- if (!argcnt) {
- if (modified) {
- es->cbuf[es->linelen] = '\0';
- source->line++;
- histsave(source->line, es->cbuf, 1);
- } else
- argcnt = source->line + 1
- - (hlast - hnum);
- }
- shf_snprintf(es->cbuf, es->cbufsize,
- argcnt ? "%s %d" : "%s",
- "fc -e ${VISUAL:-${EDITOR:-vi}} --",
- argcnt);
- es->linelen = strlen(es->cbuf);
- return 2;
-
- case 'x':
- if (es->linelen == 0)
- return -1;
- modified = 1; hnum = hlast;
- if (es->cursor + argcnt > es->linelen)
- argcnt = es->linelen - es->cursor;
- yank_range(es->cursor, es->cursor + argcnt);
- del_range(es->cursor, es->cursor + argcnt);
- break;
-
- case 'X':
- if (es->cursor > 0) {
- modified = 1; hnum = hlast;
- if (es->cursor < argcnt)
- argcnt = es->cursor;
- yank_range(es->cursor - argcnt, es->cursor);
- del_range(es->cursor - argcnt, es->cursor);
- es->cursor -= argcnt;
- } else
- return -1;
- break;
-
- case 'u':
- t = es;
- es = undo;
- undo = t;
- break;
-
- case 'U':
- if (!modified)
- return -1;
- if (grabhist(modified, ohnum) < 0)
- return -1;
- modified = 0;
- hnum = ohnum;
- break;
-
- case '?':
- if (hnum == hlast)
- hnum = -1;
- /* ahhh */
- case '/':
- c3 = 1;
- srchlen = 0;
- lastsearch = *cmd;
- /* fall through */
- case 'n':
- case 'N':
- if (lastsearch == ' ')
- return -1;
- if (lastsearch == '?')
- c1 = 1;
- else
- c1 = 0;
- if (*cmd == 'N')
- c1 = !c1;
- if ((c2 = grabsearch(modified, hnum,
- c1, srchpat)) < 0) {
- if (c3) {
- restore_cbuf();
- refresh(0);
- }
- return -1;
- } else {
- modified = 0;
- hnum = c2;
- ohnum = hnum;
- }
- break;
- case '_': {
- int inspace;
- char *p, *sp;
-
- if (histnum(-1) < 0)
- return -1;
- p = *histpos();
-#define issp(c) (isspace((c)) || (c) == '\n')
- if (argcnt) {
- while (*p && issp(*p))
- p++;
- while (*p && --argcnt) {
- while (*p && !issp(*p))
- p++;
- while (*p && issp(*p))
- p++;
- }
- if (!*p)
- return -1;
- sp = p;
- } else {
- sp = p;
- inspace = 0;
- while (*p) {
- if (issp(*p))
- inspace = 1;
- else if (inspace) {
- inspace = 0;
- sp = p;
- }
- p++;
- }
- p = sp;
- }
- modified = 1; hnum = hlast;
- if (es->cursor != es->linelen)
- es->cursor++;
- while (*p && !issp(*p)) {
- argcnt++;
- p++;
- }
- if (putbuf(space, 1, 0) != 0)
- argcnt = -1;
- else if (putbuf(sp, argcnt, 0) != 0)
- argcnt = -1;
- if (argcnt < 0) {
- if (es->cursor != 0)
- es->cursor--;
- return -1;
- }
- insert = INSERT;
- }
- break;
-
- case '~': {
- char *p;
- int i;
-
- if (es->linelen == 0)
- return -1;
- for (i = 0; i < argcnt; i++) {
- p = &es->cbuf[es->cursor];
- if (islower(*p)) {
- modified = 1; hnum = hlast;
- *p = toupper(*p);
- } else if (isupper(*p)) {
- modified = 1; hnum = hlast;
- *p = tolower(*p);
- }
- if (es->cursor < es->linelen - 1)
- es->cursor++;
- }
- break;
- }
-
- case '#':
- {
- int ret = x_do_comment(es->cbuf, es->cbufsize,
- &es->linelen);
- if (ret >= 0)
- es->cursor = 0;
- return ret;
- }
-
- case '=': /* at&t ksh */
- case Ctrl('e'): /* Nonstandard vi/ksh */
- print_expansions(es, 1);
- break;
-
-
- case Ctrl('i'): /* Nonstandard vi/ksh */
- if (!Flag(FVITABCOMPLETE))
- return -1;
- complete_word(1, argcnt);
- break;
-
- case Ctrl('['): /* some annoying at&t ksh's */
- if (!Flag(FVIESCCOMPLETE))
- return -1;
- case '\\': /* at&t ksh */
- case Ctrl('f'): /* Nonstandard vi/ksh */
- complete_word(1, argcnt);
- break;
-
-
- case '*': /* at&t ksh */
- case Ctrl('x'): /* Nonstandard vi/ksh */
- expand_word(1);
- break;
- }
- if (insert == 0 && es->cursor != 0 && es->cursor >= es->linelen)
- es->cursor--;
- }
- return 0;
-}
-
-static int
-domove(argcnt, cmd, sub)
- int argcnt;
- const char *cmd;
- int sub;
-{
- int bcount, UNINITIALIZED(i), t;
- int UNINITIALIZED(ncursor);
-
- switch (*cmd) {
-
- case 'b':
- if (!sub && es->cursor == 0)
- return -1;
- ncursor = backword(argcnt);
- break;
-
- case 'B':
- if (!sub && es->cursor == 0)
- return -1;
- ncursor = Backword(argcnt);
- break;
-
- case 'e':
- if (!sub && es->cursor + 1 >= es->linelen)
- return -1;
- ncursor = endword(argcnt);
- if (sub && ncursor < es->linelen)
- ncursor++;
- break;
-
- case 'E':
- if (!sub && es->cursor + 1 >= es->linelen)
- return -1;
- ncursor = Endword(argcnt);
- if (sub && ncursor < es->linelen)
- ncursor++;
- break;
-
- case 'f':
- case 'F':
- case 't':
- case 'T':
- fsavecmd = *cmd;
- fsavech = cmd[1];
- /* drop through */
-
- case ',':
- case ';':
- if (fsavecmd == ' ')
- return -1;
- i = fsavecmd == 'f' || fsavecmd == 'F';
- t = fsavecmd > 'a';
- if (*cmd == ',')
- t = !t;
- if ((ncursor = findch(fsavech, argcnt, t, i)) < 0)
- return -1;
- if (sub && t)
- ncursor++;
- break;
-
- case 'h':
- case Ctrl('h'):
- if (!sub && es->cursor == 0)
- return -1;
- ncursor = es->cursor - argcnt;
- if (ncursor < 0)
- ncursor = 0;
- break;
-
- case ' ':
- case 'l':
- if (!sub && es->cursor + 1 >= es->linelen)
- return -1;
- if (es->linelen != 0) {
- ncursor = es->cursor + argcnt;
- if (ncursor > es->linelen)
- ncursor = es->linelen;
- }
- break;
-
- case 'w':
- if (!sub && es->cursor + 1 >= es->linelen)
- return -1;
- ncursor = forwword(argcnt);
- break;
-
- case 'W':
- if (!sub && es->cursor + 1 >= es->linelen)
- return -1;
- ncursor = Forwword(argcnt);
- break;
-
- case '0':
- ncursor = 0;
- break;
-
- case '^':
- ncursor = 0;
- while (ncursor < es->linelen - 1 && isspace(es->cbuf[ncursor]))
- ncursor++;
- break;
-
- case '|':
- ncursor = argcnt;
- if (ncursor > es->linelen)
- ncursor = es->linelen;
- if (ncursor)
- ncursor--;
- break;
-
- case '$':
- if (es->linelen != 0)
- ncursor = es->linelen;
- else
- ncursor = 0;
- break;
-
- case '%':
- ncursor = es->cursor;
- while (ncursor < es->linelen &&
- (i = bracktype(es->cbuf[ncursor])) == 0)
- ncursor++;
- if (ncursor == es->linelen)
- return -1;
- bcount = 1;
- do {
- if (i > 0) {
- if (++ncursor >= es->linelen)
- return -1;
- } else {
- if (--ncursor < 0)
- return -1;
- }
- t = bracktype(es->cbuf[ncursor]);
- if (t == i)
- bcount++;
- else if (t == -i)
- bcount--;
- } while (bcount != 0);
- if (sub && i > 0)
- ncursor++;
- break;
-
- default:
- return -1;
- }
- return ncursor;
-}
-
-static int
-redo_insert(count)
- int count;
-{
- while (count-- > 0)
- if (putbuf(ibuf, inslen, insert==REPLACE) != 0)
- return -1;
- if (es->cursor > 0)
- es->cursor--;
- insert = 0;
- return 0;
-}
-
-static void
-yank_range(a, b)
- int a, b;
-{
- yanklen = b - a;
- if (yanklen != 0)
- memmove(ybuf, &es->cbuf[a], yanklen);
-}
-
-static int
-bracktype(ch)
- int ch;
-{
- switch (ch) {
-
- case '(':
- return 1;
-
- case '[':
- return 2;
-
- case '{':
- return 3;
-
- case ')':
- return -1;
-
- case ']':
- return -2;
-
- case '}':
- return -3;
-
- default:
- return 0;
- }
-}
-
-/*
- * Non user interface editor routines below here
- */
-
-static int cur_col; /* current column on line */
-static int pwidth; /* width of prompt */
-static int prompt_trunc; /* how much of prompt to truncate */
-static int prompt_skip; /* how much of prompt to skip */
-static int winwidth; /* width of window */
-static char *wbuf[2]; /* window buffers */
-static int wbuf_len; /* length of window buffers (x_cols-3)*/
-static int win; /* window buffer in use */
-static char morec; /* more character at right of window */
-static int lastref; /* argument to last refresh() */
-static char holdbuf[CMDLEN]; /* place to hold last edit buffer */
-static int holdlen; /* length of holdbuf */
-
-static void
-save_cbuf()
-{
- memmove(holdbuf, es->cbuf, es->linelen);
- holdlen = es->linelen;
- holdbuf[holdlen] = '\0';
-}
-
-static void
-restore_cbuf()
-{
- es->cursor = 0;
- es->linelen = holdlen;
- memmove(es->cbuf, holdbuf, holdlen);
-}
-
-/* return a new edstate */
-static struct edstate *
-save_edstate(old)
- struct edstate *old;
-{
- struct edstate *new;
-
- new = (struct edstate *)alloc(sizeof(struct edstate), APERM);
- new->cbuf = alloc(old->cbufsize, APERM);
- new->cbufsize = old->cbufsize;
- strcpy(new->cbuf, old->cbuf);
- new->linelen = old->linelen;
- new->cursor = old->cursor;
- new->winleft = old->winleft;
- return new;
-}
-
-static void
-restore_edstate(new, old)
- struct edstate *old, *new;
-{
- strncpy(new->cbuf, old->cbuf, old->linelen);
- new->linelen = old->linelen;
- new->cursor = old->cursor;
- new->winleft = old->winleft;
- free_edstate(old);
-}
-
-static void
-free_edstate(old)
- struct edstate *old;
-{
- afree(old->cbuf, APERM);
- afree((char *)old, APERM);
-}
-
-
-
-static void
-edit_reset(buf, len)
- char *buf;
- size_t len;
-{
- const char *p;
-
- es = &ebuf;
- es->cbuf = buf;
- es->cbufsize = len;
- undo = &undobuf;
- undo->cbufsize = len;
-
- es->linelen = undo->linelen = 0;
- es->cursor = undo->cursor = 0;
- es->winleft = undo->winleft = 0;
-
- cur_col = pwidth = promptlen(prompt, &p);
- prompt_skip = p - prompt;
- if (pwidth > x_cols - 3 - MIN_EDIT_SPACE) {
- cur_col = x_cols - 3 - MIN_EDIT_SPACE;
- prompt_trunc = pwidth - cur_col;
- pwidth -= prompt_trunc;
- } else
- prompt_trunc = 0;
- if (!wbuf_len || wbuf_len != x_cols - 3) {
- wbuf_len = x_cols - 3;
- wbuf[0] = aresize(wbuf[0], wbuf_len, APERM);
- wbuf[1] = aresize(wbuf[1], wbuf_len, APERM);
- }
- (void) memset(wbuf[0], ' ', wbuf_len);
- (void) memset(wbuf[1], ' ', wbuf_len);
- winwidth = x_cols - pwidth - 3;
- win = 0;
- morec = ' ';
- lastref = 1;
- holdlen = 0;
-}
-
-static int
-putbuf(buf, len, repl)
- const char *buf;
- int len;
- int repl;
-{
- if (len == 0)
- return 0;
- if (repl) {
- if (es->cursor + len >= es->cbufsize)
- return -1;
- if (es->cursor + len > es->linelen)
- es->linelen = es->cursor + len;
- } else {
- if (es->linelen + len >= es->cbufsize)
- return -1;
- memmove(&es->cbuf[es->cursor + len], &es->cbuf[es->cursor],
- es->linelen - es->cursor);
- es->linelen += len;
- }
- memmove(&es->cbuf[es->cursor], buf, len);
- es->cursor += len;
- return 0;
-}
-
-static void
-del_range(a, b)
- int a, b;
-{
- if (es->linelen != b)
- memmove(&es->cbuf[a], &es->cbuf[b], es->linelen - b);
- es->linelen -= b - a;
-}
-
-static int
-findch(ch, cnt, forw, incl)
- int ch;
- int cnt;
- int forw;
- int incl;
-{
- int ncursor;
-
- if (es->linelen == 0)
- return -1;
- ncursor = es->cursor;
- while (cnt--) {
- do {
- if (forw) {
- if (++ncursor == es->linelen)
- return -1;
- } else {
- if (--ncursor < 0)
- return -1;
- }
- } while (es->cbuf[ncursor] != ch);
- }
- if (!incl) {
- if (forw)
- ncursor--;
- else
- ncursor++;
- }
- return ncursor;
-}
-
-static int
-forwword(argcnt)
- int argcnt;
-{
- int ncursor;
-
- ncursor = es->cursor;
- while (ncursor < es->linelen && argcnt--) {
- if (is_wordch(es->cbuf[ncursor]))
- while (is_wordch(es->cbuf[ncursor]) &&
- ncursor < es->linelen)
- ncursor++;
- else if (!isspace(es->cbuf[ncursor]))
- while (!is_wordch(es->cbuf[ncursor]) &&
- !isspace(es->cbuf[ncursor]) &&
- ncursor < es->linelen)
- ncursor++;
- while (isspace(es->cbuf[ncursor]) && ncursor < es->linelen)
- ncursor++;
- }
- return ncursor;
-}
-
-static int
-backword(argcnt)
- int argcnt;
-{
- int ncursor;
-
- ncursor = es->cursor;
- while (ncursor > 0 && argcnt--) {
- while (--ncursor > 0 && isspace(es->cbuf[ncursor]))
- ;
- if (ncursor > 0) {
- if (is_wordch(es->cbuf[ncursor]))
- while (--ncursor >= 0 &&
- is_wordch(es->cbuf[ncursor]))
- ;
- else
- while (--ncursor >= 0 &&
- !is_wordch(es->cbuf[ncursor]) &&
- !isspace(es->cbuf[ncursor]))
- ;
- ncursor++;
- }
- }
- return ncursor;
-}
-
-static int
-endword(argcnt)
- int argcnt;
-{
- int ncursor;
-
- ncursor = es->cursor;
- while (ncursor < es->linelen && argcnt--) {
- while (++ncursor < es->linelen - 1 &&
- isspace(es->cbuf[ncursor]))
- ;
- if (ncursor < es->linelen - 1) {
- if (is_wordch(es->cbuf[ncursor]))
- while (++ncursor < es->linelen &&
- is_wordch(es->cbuf[ncursor]))
- ;
- else
- while (++ncursor < es->linelen &&
- !is_wordch(es->cbuf[ncursor]) &&
- !isspace(es->cbuf[ncursor]))
- ;
- ncursor--;
- }
- }
- return ncursor;
-}
-
-static int
-Forwword(argcnt)
- int argcnt;
-{
- int ncursor;
-
- ncursor = es->cursor;
- while (ncursor < es->linelen && argcnt--) {
- while (!isspace(es->cbuf[ncursor]) && ncursor < es->linelen)
- ncursor++;
- while (isspace(es->cbuf[ncursor]) && ncursor < es->linelen)
- ncursor++;
- }
- return ncursor;
-}
-
-static int
-Backword(argcnt)
- int argcnt;
-{
- int ncursor;
-
- ncursor = es->cursor;
- while (ncursor > 0 && argcnt--) {
- while (--ncursor >= 0 && isspace(es->cbuf[ncursor]))
- ;
- while (ncursor >= 0 && !isspace(es->cbuf[ncursor]))
- ncursor--;
- ncursor++;
- }
- return ncursor;
-}
-
-static int
-Endword(argcnt)
- int argcnt;
-{
- int ncursor;
-
- ncursor = es->cursor;
- while (ncursor < es->linelen - 1 && argcnt--) {
- while (++ncursor < es->linelen - 1 &&
- isspace(es->cbuf[ncursor]))
- ;
- if (ncursor < es->linelen - 1) {
- while (++ncursor < es->linelen &&
- !isspace(es->cbuf[ncursor]))
- ;
- ncursor--;
- }
- }
- return ncursor;
-}
-
-static int
-grabhist(save, n)
- int save;
- int n;
-{
- char *hptr;
-
- if (n < 0 || n > hlast)
- return -1;
- if (n == hlast) {
- restore_cbuf();
- ohnum = n;
- return 0;
- }
- (void) histnum(n);
- if ((hptr = *histpos()) == NULL) {
- internal_errorf(0, "grabhist: bad history array");
- return -1;
- }
- if (save)
- save_cbuf();
- if ((es->linelen = strlen(hptr)) >= es->cbufsize)
- es->linelen = es->cbufsize - 1;
- memmove(es->cbuf, hptr, es->linelen);
- es->cursor = 0;
- ohnum = n;
- return 0;
-}
-
-static int
-grabsearch(save, start, fwd, pat)
- int save, start, fwd;
- char *pat;
-{
- char *hptr;
- int hist;
- int anchored;
-
- if ((start == 0 && fwd == 0) || (start >= hlast-1 && fwd == 1))
- return -1;
- if (fwd)
- start++;
- else
- start--;
- anchored = *pat == '^' ? (++pat, 1) : 0;
- if ((hist = findhist(start, fwd, pat, anchored)) < 0) {
- /* if (start != 0 && fwd && match(holdbuf, pat) >= 0) { */
- /* XXX should FILECMP be strncmp? */
- if (start != 0 && fwd && FILECMP(holdbuf, pat) >= 0) {
- restore_cbuf();
- return 0;
- } else
- return -1;
- }
- if (save)
- save_cbuf();
- histnum(hist);
- hptr = *histpos();
- if ((es->linelen = strlen(hptr)) >= es->cbufsize)
- es->linelen = es->cbufsize - 1;
- memmove(es->cbuf, hptr, es->linelen);
- es->cursor = 0;
- return hist;
-}
-
-static void
-redraw_line(newline)
- int newline;
-{
- (void) memset(wbuf[win], ' ', wbuf_len);
- if (newline) {
- x_putc('\r');
- x_putc('\n');
- }
- vi_pprompt(0);
- cur_col = pwidth;
- morec = ' ';
-}
-
-static void
-refresh(leftside)
- int leftside;
-{
- if (leftside < 0)
- leftside = lastref;
- else
- lastref = leftside;
- if (outofwin())
- rewindow();
- display(wbuf[1 - win], wbuf[win], leftside);
- win = 1 - win;
-}
-
-static int
-outofwin()
-{
- int cur, col;
-
- if (es->cursor < es->winleft)
- return 1;
- col = 0;
- cur = es->winleft;
- while (cur < es->cursor)
- col = newcol((unsigned char) es->cbuf[cur++], col);
- if (col >= winwidth)
- return 1;
- return 0;
-}
-
-static void
-rewindow()
-{
- register int tcur, tcol;
- int holdcur1, holdcol1;
- int holdcur2, holdcol2;
-
- holdcur1 = holdcur2 = tcur = 0;
- holdcol1 = holdcol2 = tcol = 0;
- while (tcur < es->cursor) {
- if (tcol - holdcol2 > winwidth / 2) {
- holdcur1 = holdcur2;
- holdcol1 = holdcol2;
- holdcur2 = tcur;
- holdcol2 = tcol;
- }
- tcol = newcol((unsigned char) es->cbuf[tcur++], tcol);
- }
- while (tcol - holdcol1 > winwidth / 2)
- holdcol1 = newcol((unsigned char) es->cbuf[holdcur1++],
- holdcol1);
- es->winleft = holdcur1;
-}
-
-static int
-newcol(ch, col)
- int ch, col;
-{
- if (ch == '\t')
- return (col | 7) + 1;
- return col + char_len(ch);
-}
-
-static void
-display(wb1, wb2, leftside)
- char *wb1, *wb2;
- int leftside;
-{
- unsigned char ch;
- char *twb1, *twb2, mc;
- int cur, col, cnt;
- int UNINITIALIZED(ncol);
- int moreright;
-
- col = 0;
- cur = es->winleft;
- moreright = 0;
- twb1 = wb1;
- while (col < winwidth && cur < es->linelen) {
- if (cur == es->cursor && leftside)
- ncol = col + pwidth;
- if ((ch = es->cbuf[cur]) == '\t') {
- do {
- *twb1++ = ' ';
- } while (++col < winwidth && (col & 7) != 0);
- } else {
- if ((ch & 0x80) && Flag(FVISHOW8)) {
- *twb1++ = 'M';
- if (++col < winwidth) {
- *twb1++ = '-';
- col++;
- }
- ch &= 0x7f;
- }
- if (col < winwidth) {
- if (ch < ' ' || ch == 0x7f) {
- *twb1++ = '^';
- if (++col < winwidth) {
- *twb1++ = ch ^ '@';
- col++;
- }
- } else {
- *twb1++ = ch;
- col++;
- }
- }
- }
- if (cur == es->cursor && !leftside)
- ncol = col + pwidth - 1;
- cur++;
- }
- if (cur == es->cursor)
- ncol = col + pwidth;
- if (col < winwidth) {
- while (col < winwidth) {
- *twb1++ = ' ';
- col++;
- }
- } else
- moreright++;
- *twb1 = ' ';
-
- col = pwidth;
- cnt = winwidth;
- twb1 = wb1;
- twb2 = wb2;
- while (cnt--) {
- if (*twb1 != *twb2) {
- if (cur_col != col)
- ed_mov_opt(col, wb1);
- x_putc(*twb1);
- cur_col++;
- }
- twb1++;
- twb2++;
- col++;
- }
- if (es->winleft > 0 && moreright)
- /* POSIX says to use * for this but that is a globbing
- * character and may confuse people; + is more innocuous
- */
- mc = '+';
- else if (es->winleft > 0)
- mc = '<';
- else if (moreright)
- mc = '>';
- else
- mc = ' ';
- if (mc != morec) {
- ed_mov_opt(pwidth + winwidth + 1, wb1);
- x_putc(mc);
- cur_col++;
- morec = mc;
- }
- if (cur_col != ncol)
- ed_mov_opt(ncol, wb1);
-}
-
-static void
-ed_mov_opt(col, wb)
- int col;
- char *wb;
-{
- if (col < cur_col) {
- if (col + 1 < cur_col - col) {
- x_putc('\r');
- vi_pprompt(0);
- cur_col = pwidth;
- while (cur_col++ < col)
- x_putc(*wb++);
- } else {
- while (cur_col-- > col)
- x_putc('\b');
- }
- } else {
- wb = &wb[cur_col - pwidth];
- while (cur_col++ < col)
- x_putc(*wb++);
- }
- cur_col = col;
-}
-
-
-/* replace word with all expansions (ie, expand word*) */
-static int
-expand_word(command)
- int command;
-{
- static struct edstate *buf;
- int rval = 0;
- int nwords;
- int start, end;
- char **words;
- int i;
-
- /* Undo previous expansion */
- if (command == 0 && expanded == EXPAND && buf) {
- restore_edstate(es, buf);
- buf = 0;
- expanded = NONE;
- return 0;
- }
- if (buf) {
- free_edstate(buf);
- buf = 0;
- }
-
- nwords = x_cf_glob(XCF_COMMAND_FILE|XCF_FULLPATH,
- es->cbuf, es->linelen, es->cursor,
- &start, &end, &words, (int *) 0);
- if (nwords == 0) {
- vi_error();
- return -1;
- }
-
- buf = save_edstate(es);
- expanded = EXPAND;
- del_range(start, end);
- es->cursor = start;
- for (i = 0; i < nwords; ) {
- if (putbuf(words[i], (int) strlen(words[i]), 0) != 0) {
- rval = -1;
- break;
- }
- if (++i < nwords && putbuf(space, 1, 0) != 0) {
- rval = -1;
- break;
- }
- }
- i = buf->cursor - end;
- if (rval == 0 && i > 0)
- es->cursor += i;
- modified = 1; hnum = hlast;
- insert = INSERT;
- lastac = 0;
- refresh(0);
- return rval;
-}
-
-static int
-complete_word(command, count)
- int command;
- int count;
-{
- static struct edstate *buf;
- int rval = 0;
- int nwords;
- int start, end;
- char **words;
- char *match;
- int match_len;
- int is_unique;
- int is_command;
-
- /* Undo previous completion */
- if (command == 0 && expanded == COMPLETE && buf) {
- print_expansions(buf, 0);
- expanded = PRINT;
- return 0;
- }
- if (command == 0 && expanded == PRINT && buf) {
- restore_edstate(es, buf);
- buf = 0;
- expanded = NONE;
- return 0;
- }
- if (buf) {
- free_edstate(buf);
- buf = 0;
- }
-
- /* XCF_FULLPATH for count 'cause the menu printed by print_expansions()
- * was done this way.
- */
- nwords = x_cf_glob(XCF_COMMAND_FILE | (count ? XCF_FULLPATH : 0),
- es->cbuf, es->linelen, es->cursor,
- &start, &end, &words, &is_command);
- if (nwords == 0) {
- vi_error();
- return -1;
- }
- if (count) {
- int i;
-
- count--;
- if (count >= nwords) {
- vi_error();
- x_print_expansions(nwords, words, is_command);
- x_free_words(nwords, words);
- redraw_line(0);
- return -1;
- }
- /*
- * Expand the count'th word to its basename
- */
- if (is_command) {
- match = words[count]
- + x_basename(words[count], (char *) 0);
- /* If more than one possible match, use full path */
- for (i = 0; i < nwords; i++)
- if (i != count &&
- FILECMP(words[i]
- + x_basename(words[i], (char *) 0),
- match) == 0)
- {
- match = words[count];
- break;
- }
- } else
- match = words[count];
- match_len = strlen(match);
- is_unique = 1;
- /* expanded = PRINT; next call undo */
- } else {
- match = words[0];
- match_len = x_longest_prefix(nwords, words);
- expanded = COMPLETE; /* next call will list completions */
- is_unique = nwords == 1;
- }
-
- buf = save_edstate(es);
- del_range(start, end);
- es->cursor = start;
- if (putbuf(match, match_len, 0) != 0)
- rval = -1;
- else if (is_unique) {
- /* If exact match, don't undo. Allows directory completions
- * to be used (ie, complete the next portion of the path).
- */
- expanded = NONE;
-
- /* If not a directory, add a space to the end... */
- if (match_len > 0 && !ISDIRSEP(match[match_len - 1]))
- rval = putbuf(space, 1, 0);
- }
- x_free_words(nwords, words);
-
- modified = 1; hnum = hlast;
- insert = INSERT;
- lastac = 0; /* prevent this from being redone... */
- refresh(0);
-
- return rval;
-}
-
-static int
-print_expansions(e, command)
- struct edstate *e;
- int command;
-{
- int nwords;
- int start, end;
- char **words;
- int is_command;
-
- nwords = x_cf_glob(XCF_COMMAND_FILE|XCF_FULLPATH,
- e->cbuf, e->linelen, e->cursor,
- &start, &end, &words, &is_command);
- if (nwords == 0) {
- vi_error();
- return -1;
- }
- x_print_expansions(nwords, words, is_command);
- x_free_words(nwords, words);
- redraw_line(0);
- return 0;
-}
-
-/* How long is char when displayed (not counting tabs) */
-static int
-char_len(c)
- int c;
-{
- int len = 1;
-
- if ((c & 0x80) && Flag(FVISHOW8)) {
- len += 2;
- c &= 0x7f;
- }
- if (c < ' ' || c == 0x7f)
- len++;
- return len;
-}
-
-/* Similar to x_zotc(emacs.c), but no tab wierdness */
-static void
-x_vi_zotc(c)
- int c;
-{
- if (Flag(FVISHOW8) && (c & 0x80)) {
- x_puts("M-");
- c &= 0x7f;
- }
- if (c < ' ' || c == 0x7f) {
- x_putc('^');
- c ^= '@';
- }
- x_putc(c);
-}
-
-static void
-vi_pprompt(full)
- int full;
-{
- pprompt(prompt + (full ? 0 : prompt_skip), prompt_trunc);
-}
-
-static void
-vi_error()
-{
- /* Beem out of any macros as soon as an error occurs */
- vi_macro_reset();
- x_putc(BEL);
- x_flush();
-}
-
-static void
-vi_macro_reset()
-{
- if (macro.p) {
- afree(macro.buf, APERM);
- memset((char *) &macro, 0, sizeof(macro));
- }
-}
-
-#endif /* VI */
diff --git a/distrib/alpha/inst-common/list b/distrib/alpha/inst-common/list
index f4298bf4915..709482c41bc 100644
--- a/distrib/alpha/inst-common/list
+++ b/distrib/alpha/inst-common/list
@@ -1,5 +1,5 @@
#
-# $OpenBSD: list,v 1.8 1997/10/30 21:17:53 niklas Exp $
+# $OpenBSD: list,v 1.9 1997/12/02 02:29:17 deraadt Exp $
#
# copy the crunched binary, link to it, and kill it
@@ -18,8 +18,8 @@ LINK raminst bin/ls
#LINK raminst bin/hostname
LINK raminst bin/mkdir
LINK raminst bin/mv
-LINK raminst bin/pdksh bin/sh
-ARGVLINK pdksh -sh
+LINK raminst bin/ksh bin/sh
+ARGVLINK ksh -sh
#LINK raminst bin/pwd
LINK raminst bin/rm
LINK raminst bin/stty
diff --git a/distrib/alpha/ramdisk/raminst.conf b/distrib/alpha/ramdisk/raminst.conf
index 8dfcc318b4b..ec9201c2c87 100644
--- a/distrib/alpha/ramdisk/raminst.conf
+++ b/distrib/alpha/ramdisk/raminst.conf
@@ -1,5 +1,5 @@
#
-# $OpenBSD: raminst.conf,v 1.10 1997/09/17 19:46:24 millert Exp $
+# $OpenBSD: raminst.conf,v 1.11 1997/12/02 02:29:22 deraadt Exp $
#
# ram.conf - unified binary for the RAM disk
#
@@ -9,14 +9,14 @@ srcdirs gnu/usr.bin sys/arch/alpha/stand
progs cat chmod chown cp dd df disklabel ed grep expr fsck_ffs ftp
progs gzip ifconfig init installboot less ln ls mkdir mknod mount
-progs mount_cd9660 mount_kernfs mount_ffs mount_nfs mv newfs pdksh
+progs mount_cd9660 mount_kernfs mount_ffs mount_nfs mv newfs ksh
progs reboot rm route rsh sed sleep stty pax umount
#progs slattach sync tip
ln chown chgrp
ln fsck_ffs fsck
-ln pdksh sh
-ln pdksh -sh # init invokes the shell this way
+ln ksh sh
+ln ksh -sh # init invokes the shell this way
ln mount_ffs ffs
ln newfs mount_mfs
ln grep egrep
diff --git a/distrib/arc/common/instbin-krb.conf b/distrib/arc/common/instbin-krb.conf
index b718e2a1b7a..1fccba155e1 100644
--- a/distrib/arc/common/instbin-krb.conf
+++ b/distrib/arc/common/instbin-krb.conf
@@ -1,4 +1,4 @@
-# $OpenBSD: instbin-krb.conf,v 1.1 1997/05/14 21:13:31 pefo Exp $
+# $OpenBSD: instbin-krb.conf,v 1.2 1997/12/02 02:29:29 deraadt Exp $
#
# instbin.conf - unified binary for the inst/upgr floppies
#
@@ -9,7 +9,7 @@ progs awk bad144 cat chmod chown cp dd df disklabel ed expr fsck_ffs
progs ftp fdisk
progs ifconfig init less ln ls mkdir mknod mount mount_cd9660
progs mount_ffs mount_msdos mount_nfs mount_kernfs
-progs mv newfs pax pdksh ping pppd pwd reboot rm route
+progs mv newfs pax ksh ping pppd pwd reboot rm route
progs scsi sed shutdown slattach stty sync test tip umount
progs rsh restore gzip
@@ -18,8 +18,8 @@ ln fsck_ffs fsck
ln less more
ln pax tar
ln pax cpio
-ln pdksh sh
-ln pdksh -sh # init invokes the shell this way
+ln ksh sh
+ln ksh -sh # init invokes the shell this way
ln test [
ln reboot halt
diff --git a/distrib/arc/common/instbin.conf b/distrib/arc/common/instbin.conf
index e6ecf418118..fc91babd016 100644
--- a/distrib/arc/common/instbin.conf
+++ b/distrib/arc/common/instbin.conf
@@ -1,4 +1,4 @@
-# $OpenBSD: instbin.conf,v 1.1 1997/05/14 21:13:31 pefo Exp $
+# $OpenBSD: instbin.conf,v 1.2 1997/12/02 02:29:31 deraadt Exp $
#
# instbin.conf - unified binary for the inst/upgr floppies
#
@@ -9,7 +9,7 @@ progs awk bad144 cat chat chmod chown cp dd df disklabel ed
progs expr fsck_ffs ftp fdisk
progs ifconfig init less ln ls mkdir mknod mount mount_cd9660
progs mount_ffs mount_msdos mount_nfs mount_kernfs
-progs mv newfs pax pdksh ping pppd pwd reboot rm route
+progs mv newfs pax ksh ping pppd pwd reboot rm route
progs scsi sed shutdown slattach stty sync test tip umount
progs rsh restore gzip
@@ -18,8 +18,8 @@ ln fsck_ffs fsck
ln less more
ln pax tar
ln pax cpio
-ln pdksh sh
-ln pdksh -sh # init invokes the shell this way
+ln ksh sh
+ln ksh -sh # init invokes the shell this way
ln test [
ln reboot halt
diff --git a/distrib/arc/ramdisk/list b/distrib/arc/ramdisk/list
index 437e6b84d7a..b6db031dd52 100644
--- a/distrib/arc/ramdisk/list
+++ b/distrib/arc/ramdisk/list
@@ -1,4 +1,4 @@
-# $OpenBSD: list,v 1.7 1997/09/19 00:14:02 deraadt Exp $
+# $OpenBSD: list,v 1.8 1997/12/02 02:29:36 deraadt Exp $
SRCDIRS distrib/special
SRCDIRS usr.bin bin sbin usr.sbin gnu/usr.bin
@@ -21,8 +21,8 @@ LINK instbin bin/mt
LINK instbin bin/mv
LINK instbin bin/pax bin/tar bin/cpio
LINK instbin bin/rm
-LINK instbin bin/pdksh bin/sh
-ARGVLINK pdksh -sh
+LINK instbin bin/ksh bin/sh
+ARGVLINK ksh -sh
LINK instbin bin/sleep
LINK instbin bin/stty
LINK instbin bin/sync
diff --git a/distrib/hp300/ramdisk/list b/distrib/hp300/ramdisk/list
index c5aca7b1fac..14b7bd3a82d 100644
--- a/distrib/hp300/ramdisk/list
+++ b/distrib/hp300/ramdisk/list
@@ -1,4 +1,4 @@
-# $OpenBSD: list,v 1.7 1997/10/21 00:35:32 downsj Exp $
+# $OpenBSD: list,v 1.8 1997/12/02 02:29:48 deraadt Exp $
COPY ${OBJDIR}/raminst raminst
LINK raminst bin/cat
@@ -16,7 +16,6 @@ LINK raminst bin/mkdir
LINK raminst bin/mv
LINK raminst bin/pwd
LINK raminst bin/rm
-#COPY ${OBJDIR}/sh bin/sh
LINK raminst bin/sh
LINK bin/sh bin/-sh
LINK raminst bin/sleep
diff --git a/distrib/hp300/ramdisk/raminst.conf b/distrib/hp300/ramdisk/raminst.conf
index 7262aab8886..c2dc70e8300 100644
--- a/distrib/hp300/ramdisk/raminst.conf
+++ b/distrib/hp300/ramdisk/raminst.conf
@@ -1,5 +1,5 @@
#
-# $OpenBSD: raminst.conf,v 1.5 1997/10/20 02:19:35 downsj Exp $
+# $OpenBSD: raminst.conf,v 1.6 1997/12/02 02:29:50 deraadt Exp $
#
# raminst.conf - unified binary for the RAM disk
#
@@ -10,15 +10,15 @@ srcdirs usr.bin/vi
progs awk cat chat chmod chown chroot cp cut dd df disklabel ed expr fsck_ffs
progs ftp grep gzip hostname ifconfig init kill less ln ls mkdir mknod mount
progs mount_cd9660 mount_ffs mount_kernfs mount_nfs
-progs mv newfs pax pdksh ping pppd pwd reboot rm route build
+progs mv newfs pax ksh ping pppd pwd reboot rm route build
progs sed shutdown slattach sleep sort strings stty sync test tip umount
progs restore
ln pax tar
ln chown chgrp
ln fsck_ffs fsck
-ln pdksh sh
-ln pdksh -sh # init invokes the shell this way
+ln ksh sh
+ln ksh -sh # init invokes the shell this way
ln test [
ln mount_ffs ffs
ln newfs mount_mfs
diff --git a/distrib/i386/floppies/common/instbin-krb.conf b/distrib/i386/floppies/common/instbin-krb.conf
index e359b007329..c1002e5732c 100644
--- a/distrib/i386/floppies/common/instbin-krb.conf
+++ b/distrib/i386/floppies/common/instbin-krb.conf
@@ -1,4 +1,4 @@
-# $OpenBSD: instbin-krb.conf,v 1.7 1997/05/07 06:03:21 deraadt Exp $
+# $OpenBSD: instbin-krb.conf,v 1.8 1997/12/02 02:29:53 deraadt Exp $
#
# instbin.conf - unified binary for the inst/upgr floppies
#
@@ -9,7 +9,7 @@ progs awk bad144 cat chmod chown cp dd df disklabel ed expr fsck_ffs
progs ftp fdisk
progs ifconfig init less ln ls mkdir mknod mount mount_cd9660
progs mount_ffs mount_msdos mount_nfs mount_kernfs
-progs mv newfs pax pdksh ping pppd pwd reboot rm route
+progs mv newfs pax ksh ping pppd pwd reboot rm route
progs scsi sed shutdown slattach stty sync test tip umount
progs rsh restore gzip
@@ -18,8 +18,8 @@ ln fsck_ffs fsck
ln less more
ln pax tar
ln pax cpio
-ln pdksh sh
-ln pdksh -sh # init invokes the shell this way
+ln ksh sh
+ln ksh -sh # init invokes the shell this way
ln test [
ln reboot halt
diff --git a/distrib/i386/floppies/common/instbin.conf b/distrib/i386/floppies/common/instbin.conf
index 829e21f9d2e..569a1355064 100644
--- a/distrib/i386/floppies/common/instbin.conf
+++ b/distrib/i386/floppies/common/instbin.conf
@@ -1,4 +1,4 @@
-# $OpenBSD: instbin.conf,v 1.6 1997/05/07 06:03:22 deraadt Exp $
+# $OpenBSD: instbin.conf,v 1.7 1997/12/02 02:29:56 deraadt Exp $
#
# instbin.conf - unified binary for the inst/upgr floppies
#
@@ -9,7 +9,7 @@ progs awk bad144 cat chat chmod chown cp dd df disklabel ed
progs expr fsck_ffs ftp fdisk
progs ifconfig init less ln ls mkdir mknod mount mount_cd9660
progs mount_ffs mount_msdos mount_nfs mount_kernfs
-progs mv newfs pax pdksh ping pppd pwd reboot rm route
+progs mv newfs pax ksh ping pppd pwd reboot rm route
progs scsi sed shutdown slattach stty sync test tip umount
progs rsh restore gzip
@@ -18,8 +18,8 @@ ln fsck_ffs fsck
ln less more
ln pax tar
ln pax cpio
-ln pdksh sh
-ln pdksh -sh # init invokes the shell this way
+ln ksh sh
+ln ksh -sh # init invokes the shell this way
ln test [
ln reboot halt
diff --git a/distrib/i386/floppies/ramdisk/instbin-nokrb.conf b/distrib/i386/floppies/ramdisk/instbin-nokrb.conf
index 03d41bd1054..7e783bdcebc 100644
--- a/distrib/i386/floppies/ramdisk/instbin-nokrb.conf
+++ b/distrib/i386/floppies/ramdisk/instbin-nokrb.conf
@@ -1,4 +1,4 @@
-# $OpenBSD: instbin-nokrb.conf,v 1.9 1997/12/01 02:43:37 deraadt Exp $
+# $OpenBSD: instbin-nokrb.conf,v 1.10 1997/12/02 02:30:01 deraadt Exp $
#
# instbin-nokrb.conf - unified binary for the inst/upgr floppies
#
@@ -10,7 +10,7 @@ progs cat chat chmod chown cp dd df disklabel ed
progs expr fsck_ffs ftp fdisk hostname
progs ifconfig init less ln ls mkdir mknod mount mount_cd9660
progs mount_ffs mount_msdos mount_nfs mount_kernfs mount_ext2fs
-progs mv newfs pax pdksh ping pppd pwd reboot rm route
+progs mv newfs pax ksh ping pppd pwd reboot rm route
progs scsi sed slattach sleep stty sync test tip umount
progs rsh restore gzip sort grep cut installboot
@@ -19,8 +19,8 @@ ln fsck_ffs fsck
ln less more
ln pax tar
ln pax cpio
-ln pdksh sh
-ln pdksh -sh # init invokes the shell this way
+ln ksh sh
+ln ksh -sh # init invokes the shell this way
ln test [
ln reboot halt
ln gzip gunzip
diff --git a/distrib/i386/floppies/ramdisk/instbin.conf b/distrib/i386/floppies/ramdisk/instbin.conf
index 4bb784c29c4..76f899ecf7a 100644
--- a/distrib/i386/floppies/ramdisk/instbin.conf
+++ b/distrib/i386/floppies/ramdisk/instbin.conf
@@ -1,4 +1,4 @@
-# $OpenBSD: instbin.conf,v 1.17 1997/12/01 02:43:38 deraadt Exp $
+# $OpenBSD: instbin.conf,v 1.18 1997/12/02 02:30:02 deraadt Exp $
#
# instbin.conf - unified binary for the inst/upgr floppies
#
@@ -10,7 +10,7 @@ progs cat chat chmod chown cp dd df disklabel ed
progs expr fsck_ffs ftp fdisk hostname
progs ifconfig init less ln ls mkdir mknod mount mount_cd9660
progs mount_ffs mount_msdos mount_nfs mount_kernfs mount_ext2fs
-progs mv newfs pax pdksh ping pppd pwd reboot rm route
+progs mv newfs pax ksh ping pppd pwd reboot rm route
progs scsi sed slattach sleep stty sync test tip umount
progs rsh restore gzip sort grep cut installboot
@@ -19,8 +19,8 @@ ln fsck_ffs fsck
ln less more
ln pax tar
ln pax cpio
-ln pdksh sh
-ln pdksh -sh # init invokes the shell this way
+ln ksh sh
+ln ksh -sh # init invokes the shell this way
ln test [
ln reboot halt
ln gzip gunzip
diff --git a/distrib/i386/floppies/ramdisk/list b/distrib/i386/floppies/ramdisk/list
index 3b8a7b18d80..1faaac32757 100644
--- a/distrib/i386/floppies/ramdisk/list
+++ b/distrib/i386/floppies/ramdisk/list
@@ -1,4 +1,4 @@
-# $OpenBSD: list,v 1.13 1997/12/01 02:43:38 deraadt Exp $
+# $OpenBSD: list,v 1.14 1997/12/02 02:30:05 deraadt Exp $
# copy the crunched binary, link to it, and kill it
COPY ${OBJDIR}/instbin instbin
@@ -17,7 +17,7 @@ LINK instbin bin/mkdir
LINK instbin bin/mv
LINK instbin bin/pwd
LINK instbin bin/rm
-LINK instbin bin/sh bin/pdksh
+LINK instbin bin/sh bin/ksh
LINK instbin bin/sleep
LINK instbin bin/stty
LINK instbin bin/sync
diff --git a/distrib/miniroot/list b/distrib/miniroot/list
index 28e6f02bb3e..c15884e626c 100644
--- a/distrib/miniroot/list
+++ b/distrib/miniroot/list
@@ -1,4 +1,4 @@
-# $OpenBSD: list,v 1.14 1997/10/02 01:11:07 deraadt Exp $
+# $OpenBSD: list,v 1.15 1997/12/02 02:30:12 deraadt Exp $
# $NetBSD: list,v 1.4.4.1 1996/06/20 20:30:26 pk Exp $
SRCDIRS distrib/special
@@ -23,7 +23,7 @@ LINK instbin bin/mv
LINK instbin bin/pax bin/tar bin/cpio
LINK instbin bin/pwd
LINK instbin bin/rm
-LINK instbin bin/pdksh bin/sh
+LINK instbin bin/ksh bin/sh
LINK instbin bin/stty
LINK instbin bin/sleep
LINK instbin bin/sync
@@ -58,7 +58,7 @@ SYMLINK ../../instbin usr/bin/build usr/bin/vi
ARGVLINK mount_ffs ffs
ARGVLINK mount_nfs nfs
ARGVLINK mount_cd9660 cd9660
-ARGVLINK pdksh -sh
+ARGVLINK ksh -sh
# various files that we need in /etc for the install
COPY ${DESTDIR}/etc/group etc/group
diff --git a/distrib/mvme68k/ramdisk/raminst.conf b/distrib/mvme68k/ramdisk/raminst.conf
index cec7f7606b7..08a037e09d1 100644
--- a/distrib/mvme68k/ramdisk/raminst.conf
+++ b/distrib/mvme68k/ramdisk/raminst.conf
@@ -11,15 +11,15 @@ srcdirs gnu/usr.bin
progs cat chmod chown cut cp dd df disklabel ed grep expr fsck_ffs ftp
progs gzip ifconfig init hostname kill ln ls mkdir mknod less mount
progs mount_cd9660 mount_kernfs mount_ffs mount_msdos mount_nfs
-progs mv newfs pwd reboot rm route sed sleep pdksh slattach sort stty
+progs mv newfs pwd reboot rm route sed sleep ksh slattach sort stty
progs sync pax test tip umount build
ln build vi
ln chown chgrp
ln fsck_ffs fsck
ln less more
-ln pdksh sh
-ln pdksh -sh # init invokes the shell this way
+ln ksh sh
+ln ksh -sh # init invokes the shell this way
ln test [
ln reboot halt
ln grep egrep
diff --git a/distrib/powerpc/ramdisk/list b/distrib/powerpc/ramdisk/list
index fd2dafe7026..51f1f751214 100644
--- a/distrib/powerpc/ramdisk/list
+++ b/distrib/powerpc/ramdisk/list
@@ -1,4 +1,4 @@
-# $OpenBSD: list,v 1.2 1997/10/15 14:09:05 pefo Exp $
+# $OpenBSD: list,v 1.3 1997/12/02 02:30:29 deraadt Exp $
SRCDIRS distrib/special
SRCDIRS usr.bin bin sbin usr.sbin gnu/usr.bin
@@ -21,8 +21,8 @@ LINK instbin bin/mt
LINK instbin bin/mv
LINK instbin bin/pax bin/tar bin/cpio
LINK instbin bin/rm
-LINK instbin bin/pdksh bin/sh
-ARGVLINK pdksh -sh
+LINK instbin bin/ksh bin/sh
+ARGVLINK ksh -sh
LINK instbin bin/sleep
LINK instbin bin/stty
LINK instbin bin/sync
diff --git a/distrib/ramdisk/list b/distrib/ramdisk/list
index 98bab9d4cbf..24db998b66e 100644
--- a/distrib/ramdisk/list
+++ b/distrib/ramdisk/list
@@ -1,4 +1,4 @@
-# $OpenBSD: list,v 1.5 1997/09/17 14:19:42 deraadt Exp $
+# $OpenBSD: list,v 1.6 1997/12/02 02:30:34 deraadt Exp $
# $NetBSD: list,v 1.4.4.1 1996/06/20 20:30:26 pk Exp $
SRCDIRS distrib/special
@@ -23,7 +23,7 @@ LINK instbin bin/mt
LINK instbin bin/mv
LINK instbin bin/pax bin/tar bin/cpio
LINK instbin bin/rm
-LINK instbin bin/pdksh bin/sh
+LINK instbin bin/ksh bin/sh
LINK instbin bin/stty
LINK instbin bin/sleep
LINK instbin bin/sync
@@ -49,7 +49,7 @@ SYMLINK ../../instbin usr/bin/gzip usr/bin/gunzip usr/bin/gzcat
SYMLINK ../../instbin usr/bin/sed
SYMLINK ../../instbin usr/bin/build usr/bin/vi
-ARGVLINK pdksh -sh
+ARGVLINK ksh -sh
# various files that we need in /etc for the install
COPY ${DESTDIR}/etc/group etc/group
diff --git a/distrib/sets/lists/base/md.alpha b/distrib/sets/lists/base/md.alpha
index 85cbe7809d8..78e146f903a 100644
--- a/distrib/sets/lists/base/md.alpha
+++ b/distrib/sets/lists/base/md.alpha
@@ -12,349 +12,6 @@
./usr/lib/gcc-lib/alpha-unknown-openbsd2.2/2.7.2.1/include
./usr/lib/gcc-lib/alpha-unknown-openbsd2.2/2.7.2.1/include/objc
./usr/lib/perl5/alpha-openbsd
-./usr/lib/perl5/alpha-openbsd/5.003
-./usr/lib/perl5/alpha-openbsd/5.003/CORE
-./usr/lib/perl5/alpha-openbsd/5.003/CORE/EXTERN.h
-./usr/lib/perl5/alpha-openbsd/5.003/CORE/INTERN.h
-./usr/lib/perl5/alpha-openbsd/5.003/CORE/XSUB.h
-./usr/lib/perl5/alpha-openbsd/5.003/CORE/av.h
-./usr/lib/perl5/alpha-openbsd/5.003/CORE/config.h
-./usr/lib/perl5/alpha-openbsd/5.003/CORE/cop.h
-./usr/lib/perl5/alpha-openbsd/5.003/CORE/cv.h
-./usr/lib/perl5/alpha-openbsd/5.003/CORE/dosish.h
-./usr/lib/perl5/alpha-openbsd/5.003/CORE/embed.h
-./usr/lib/perl5/alpha-openbsd/5.003/CORE/form.h
-./usr/lib/perl5/alpha-openbsd/5.003/CORE/gv.h
-./usr/lib/perl5/alpha-openbsd/5.003/CORE/handy.h
-./usr/lib/perl5/alpha-openbsd/5.003/CORE/hv.h
-./usr/lib/perl5/alpha-openbsd/5.003/CORE/keywords.h
-./usr/lib/perl5/alpha-openbsd/5.003/CORE/libperl.a
-./usr/lib/perl5/alpha-openbsd/5.003/CORE/mg.h
-./usr/lib/perl5/alpha-openbsd/5.003/CORE/op.h
-./usr/lib/perl5/alpha-openbsd/5.003/CORE/opcode.h
-./usr/lib/perl5/alpha-openbsd/5.003/CORE/patchlevel.h
-./usr/lib/perl5/alpha-openbsd/5.003/CORE/perl.h
-./usr/lib/perl5/alpha-openbsd/5.003/CORE/perly.h
-./usr/lib/perl5/alpha-openbsd/5.003/CORE/pp.h
-./usr/lib/perl5/alpha-openbsd/5.003/CORE/proto.h
-./usr/lib/perl5/alpha-openbsd/5.003/CORE/regcomp.h
-./usr/lib/perl5/alpha-openbsd/5.003/CORE/regexp.h
-./usr/lib/perl5/alpha-openbsd/5.003/CORE/scope.h
-./usr/lib/perl5/alpha-openbsd/5.003/CORE/sv.h
-./usr/lib/perl5/alpha-openbsd/5.003/CORE/unixish.h
-./usr/lib/perl5/alpha-openbsd/5.003/CORE/util.h
-./usr/lib/perl5/alpha-openbsd/5.003/Config.pm
-./usr/lib/perl5/alpha-openbsd/5.003/a.out.ph
-./usr/lib/perl5/alpha-openbsd/5.003/ar.ph
-./usr/lib/perl5/alpha-openbsd/5.003/arpa
-./usr/lib/perl5/alpha-openbsd/5.003/arpa/ftp.ph
-./usr/lib/perl5/alpha-openbsd/5.003/arpa/inet.ph
-./usr/lib/perl5/alpha-openbsd/5.003/arpa/nameser.ph
-./usr/lib/perl5/alpha-openbsd/5.003/arpa/telnet.ph
-./usr/lib/perl5/alpha-openbsd/5.003/arpa/tftp.ph
-./usr/lib/perl5/alpha-openbsd/5.003/assert.ph
-./usr/lib/perl5/alpha-openbsd/5.003/auto
-./usr/lib/perl5/alpha-openbsd/5.003/auto/DynaLoader
-./usr/lib/perl5/alpha-openbsd/5.003/auto/DynaLoader/DynaLoader.a
-./usr/lib/perl5/alpha-openbsd/5.003/auto/DynaLoader/extralibs.ld
-./usr/lib/perl5/alpha-openbsd/5.003/auto/Text
-./usr/lib/perl5/alpha-openbsd/5.003/auto/Text/ParseWords
-./usr/lib/perl5/alpha-openbsd/5.003/bitstring.ph
-./usr/lib/perl5/alpha-openbsd/5.003/blf.ph
-./usr/lib/perl5/alpha-openbsd/5.003/bm.ph
-./usr/lib/perl5/alpha-openbsd/5.003/com_err.ph
-./usr/lib/perl5/alpha-openbsd/5.003/cpio.ph
-./usr/lib/perl5/alpha-openbsd/5.003/ctype.ph
-./usr/lib/perl5/alpha-openbsd/5.003/curses.ph
-./usr/lib/perl5/alpha-openbsd/5.003/db.ph
-./usr/lib/perl5/alpha-openbsd/5.003/des.ph
-./usr/lib/perl5/alpha-openbsd/5.003/dirent.ph
-./usr/lib/perl5/alpha-openbsd/5.003/disktab.ph
-./usr/lib/perl5/alpha-openbsd/5.003/elf_abi.ph
-./usr/lib/perl5/alpha-openbsd/5.003/err.ph
-./usr/lib/perl5/alpha-openbsd/5.003/errno.ph
-./usr/lib/perl5/alpha-openbsd/5.003/eti.ph
-./usr/lib/perl5/alpha-openbsd/5.003/fcntl.ph
-./usr/lib/perl5/alpha-openbsd/5.003/float.ph
-./usr/lib/perl5/alpha-openbsd/5.003/fnmatch.ph
-./usr/lib/perl5/alpha-openbsd/5.003/form.ph
-./usr/lib/perl5/alpha-openbsd/5.003/frame.ph
-./usr/lib/perl5/alpha-openbsd/5.003/fstab.ph
-./usr/lib/perl5/alpha-openbsd/5.003/fts.ph
-./usr/lib/perl5/alpha-openbsd/5.003/glob.ph
-./usr/lib/perl5/alpha-openbsd/5.003/gmp.ph
-./usr/lib/perl5/alpha-openbsd/5.003/grp.ph
-./usr/lib/perl5/alpha-openbsd/5.003/histedit.ph
-./usr/lib/perl5/alpha-openbsd/5.003/ieeefp.ph
-./usr/lib/perl5/alpha-openbsd/5.003/inttypes.ph
-./usr/lib/perl5/alpha-openbsd/5.003/iso646.ph
-./usr/lib/perl5/alpha-openbsd/5.003/kvm.ph
-./usr/lib/perl5/alpha-openbsd/5.003/langinfo.ph
-./usr/lib/perl5/alpha-openbsd/5.003/libgen.ph
-./usr/lib/perl5/alpha-openbsd/5.003/limits.ph
-./usr/lib/perl5/alpha-openbsd/5.003/locale.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine
-./usr/lib/perl5/alpha-openbsd/5.003/machine/alpha_cpu.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/ansi.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/aout_machdep.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/asm.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/autoconf.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/bus.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/cdefs.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/cfbreg.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/cpu.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/cpuconf.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/db_machdep.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/disklabel.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/ecoff.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/ecoff_machdep.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/elf_machdep.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/endian.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/exec.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/fbio.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/float.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/frame.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/ieee.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/ieeefp.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/intr.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/intrcnt.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/kbio.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/kcore.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/limits.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/param.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/pcb.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/pmap.new.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/pmap.old.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/pmap.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/proc.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/profile.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/prom.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/psl.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/pte.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/ptrace.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/reg.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/rpb.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/setjmp.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/sfbreg.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/signal.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/stdarg.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/tgareg.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/types.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/varargs.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/vmparam.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/vuid_event.ph
-./usr/lib/perl5/alpha-openbsd/5.003/machine/wsconsio.ph
-./usr/lib/perl5/alpha-openbsd/5.003/malloc.ph
-./usr/lib/perl5/alpha-openbsd/5.003/math.ph
-./usr/lib/perl5/alpha-openbsd/5.003/md4.ph
-./usr/lib/perl5/alpha-openbsd/5.003/md5.ph
-./usr/lib/perl5/alpha-openbsd/5.003/memory.ph
-./usr/lib/perl5/alpha-openbsd/5.003/menu.ph
-./usr/lib/perl5/alpha-openbsd/5.003/mpool.ph
-./usr/lib/perl5/alpha-openbsd/5.003/ndbm.ph
-./usr/lib/perl5/alpha-openbsd/5.003/net
-./usr/lib/perl5/alpha-openbsd/5.003/net/bpf.ph
-./usr/lib/perl5/alpha-openbsd/5.003/net/bpfdesc.ph
-./usr/lib/perl5/alpha-openbsd/5.003/net/encap.ph
-./usr/lib/perl5/alpha-openbsd/5.003/net/if.ph
-./usr/lib/perl5/alpha-openbsd/5.003/net/if_arp.ph
-./usr/lib/perl5/alpha-openbsd/5.003/net/if_atm.ph
-./usr/lib/perl5/alpha-openbsd/5.003/net/if_dl.ph
-./usr/lib/perl5/alpha-openbsd/5.003/net/if_fddi.ph
-./usr/lib/perl5/alpha-openbsd/5.003/net/if_llc.ph
-./usr/lib/perl5/alpha-openbsd/5.003/net/if_ppp.ph
-./usr/lib/perl5/alpha-openbsd/5.003/net/if_pppvar.ph
-./usr/lib/perl5/alpha-openbsd/5.003/net/if_slvar.ph
-./usr/lib/perl5/alpha-openbsd/5.003/net/if_stripvar.ph
-./usr/lib/perl5/alpha-openbsd/5.003/net/if_tun.ph
-./usr/lib/perl5/alpha-openbsd/5.003/net/if_types.ph
-./usr/lib/perl5/alpha-openbsd/5.003/net/netisr.ph
-./usr/lib/perl5/alpha-openbsd/5.003/net/pfkeyv2.ph
-./usr/lib/perl5/alpha-openbsd/5.003/net/ppp-comp.ph
-./usr/lib/perl5/alpha-openbsd/5.003/net/ppp_defs.ph
-./usr/lib/perl5/alpha-openbsd/5.003/net/radix.ph
-./usr/lib/perl5/alpha-openbsd/5.003/net/raw_cb.ph
-./usr/lib/perl5/alpha-openbsd/5.003/net/route.ph
-./usr/lib/perl5/alpha-openbsd/5.003/net/slcompress.ph
-./usr/lib/perl5/alpha-openbsd/5.003/net/slip.ph
-./usr/lib/perl5/alpha-openbsd/5.003/net/zlib.ph
-./usr/lib/perl5/alpha-openbsd/5.003/netdb.ph
-./usr/lib/perl5/alpha-openbsd/5.003/netgroup.ph
-./usr/lib/perl5/alpha-openbsd/5.003/nl_types.ph
-./usr/lib/perl5/alpha-openbsd/5.003/nlist.ph
-./usr/lib/perl5/alpha-openbsd/5.003/ocurses.ph
-./usr/lib/perl5/alpha-openbsd/5.003/olf_abi.ph
-./usr/lib/perl5/alpha-openbsd/5.003/panel.ph
-./usr/lib/perl5/alpha-openbsd/5.003/paths.ph
-./usr/lib/perl5/alpha-openbsd/5.003/pcap-namedb.ph
-./usr/lib/perl5/alpha-openbsd/5.003/pcap.ph
-./usr/lib/perl5/alpha-openbsd/5.003/poll.ph
-./usr/lib/perl5/alpha-openbsd/5.003/protocols
-./usr/lib/perl5/alpha-openbsd/5.003/protocols/dumprestore.ph
-./usr/lib/perl5/alpha-openbsd/5.003/protocols/routed.ph
-./usr/lib/perl5/alpha-openbsd/5.003/protocols/rwhod.ph
-./usr/lib/perl5/alpha-openbsd/5.003/protocols/talkd.ph
-./usr/lib/perl5/alpha-openbsd/5.003/protocols/timed.ph
-./usr/lib/perl5/alpha-openbsd/5.003/pwd.ph
-./usr/lib/perl5/alpha-openbsd/5.003/ranlib.ph
-./usr/lib/perl5/alpha-openbsd/5.003/re_comp.ph
-./usr/lib/perl5/alpha-openbsd/5.003/regex.ph
-./usr/lib/perl5/alpha-openbsd/5.003/regexp.ph
-./usr/lib/perl5/alpha-openbsd/5.003/resolv.ph
-./usr/lib/perl5/alpha-openbsd/5.003/rmd160.ph
-./usr/lib/perl5/alpha-openbsd/5.003/scsi.ph
-./usr/lib/perl5/alpha-openbsd/5.003/search.ph
-./usr/lib/perl5/alpha-openbsd/5.003/setjmp.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sgtty.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sha1.ph
-./usr/lib/perl5/alpha-openbsd/5.003/signal.ph
-./usr/lib/perl5/alpha-openbsd/5.003/skey.ph
-./usr/lib/perl5/alpha-openbsd/5.003/stab.ph
-./usr/lib/perl5/alpha-openbsd/5.003/stdarg.ph
-./usr/lib/perl5/alpha-openbsd/5.003/stddef.ph
-./usr/lib/perl5/alpha-openbsd/5.003/stdio.ph
-./usr/lib/perl5/alpha-openbsd/5.003/stdlib.ph
-./usr/lib/perl5/alpha-openbsd/5.003/string.ph
-./usr/lib/perl5/alpha-openbsd/5.003/strings.ph
-./usr/lib/perl5/alpha-openbsd/5.003/struct.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys
-./usr/lib/perl5/alpha-openbsd/5.003/sys/acct.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/audioio.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/buf.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/callout.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/cdefs.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/cdio.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/chio.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/clist.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/conf.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/core.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/device.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/dir.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/dirent.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/disk.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/disklabel.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/dkbad.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/dkio.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/dkstat.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/dmap.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/domain.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/endian.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/errno.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/exec.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/exec_aout.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/exec_ecoff.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/exec_elf.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/exec_olf.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/exec_script.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/extent.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/fcntl.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/file.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/filedesc.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/filio.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/gmon.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/ioccom.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/ioctl.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/ioctl_compat.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/ipc.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/kcore.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/kernel.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/ktrace.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/lkm.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/localedef.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/lock.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/lockf.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/malloc.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/map.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/mbuf.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/md5k.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/mman.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/mount.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/msg.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/msgbuf.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/mtio.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/namei.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/param.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/pipe.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/poll.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/proc.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/protosw.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/ptrace.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/queue.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/reboot.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/resource.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/resourcevar.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/scanio.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/scsiio.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/select.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/sem.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/shm.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/siginfo.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/signal.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/signalvar.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/simplelock.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/socket.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/socketvar.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/sockio.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/stat.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/syscall.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/syscallargs.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/sysctl.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/syslimits.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/syslog.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/systm.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/tablet.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/termios.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/time.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/timeb.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/times.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/timex.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/tprintf.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/trace.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/tty.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/ttychars.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/ttycom.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/ttydefaults.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/ttydev.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/types.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/ucred.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/uio.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/un.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/unistd.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/unpcb.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/user.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/utsname.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/vadvise.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/vcmd.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/vlimit.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/vmmeter.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/vnode.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/vnode_if.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/vsio.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sys/wait.ph
-./usr/lib/perl5/alpha-openbsd/5.003/sysexits.ph
-./usr/lib/perl5/alpha-openbsd/5.003/syslog.ph
-./usr/lib/perl5/alpha-openbsd/5.003/tar.ph
-./usr/lib/perl5/alpha-openbsd/5.003/tcpd.ph
-./usr/lib/perl5/alpha-openbsd/5.003/term.ph
-./usr/lib/perl5/alpha-openbsd/5.003/termios.ph
-./usr/lib/perl5/alpha-openbsd/5.003/time.ph
-./usr/lib/perl5/alpha-openbsd/5.003/ttyent.ph
-./usr/lib/perl5/alpha-openbsd/5.003/tzfile.ph
-./usr/lib/perl5/alpha-openbsd/5.003/unctrl.ph
-./usr/lib/perl5/alpha-openbsd/5.003/unistd.ph
-./usr/lib/perl5/alpha-openbsd/5.003/util.ph
-./usr/lib/perl5/alpha-openbsd/5.003/utime.ph
-./usr/lib/perl5/alpha-openbsd/5.003/utmp.ph
-./usr/lib/perl5/alpha-openbsd/5.003/varargs.ph
-./usr/lib/perl5/alpha-openbsd/5.003/vis.ph
-./usr/lib/perl5/alpha-openbsd/5.003/zconf.ph
-./usr/lib/perl5/alpha-openbsd/5.003/zlib.ph
-./usr/lib/perl5/auto/Text
-./usr/lib/perl5/auto/Text/ParseWords
-./usr/lib/perl5/auto/Text/ParseWords/autosplit.ix
-./usr/lib/perl5/auto/Text/ParseWords/old_shellwords.al
-./usr/lib/perl5/auto/Text/ParseWords/quotewords.al
-./usr/lib/perl5/auto/Text/ParseWords/shellwords.al
./usr/lib/perl5/site_perl/alpha-openbsd
./usr/mdec/boot
./usr/mdec/bootxx
diff --git a/distrib/sets/lists/base/md.i386 b/distrib/sets/lists/base/md.i386
index 9ad8fcd3e25..5eae685954a 100644
--- a/distrib/sets/lists/base/md.i386
+++ b/distrib/sets/lists/base/md.i386
@@ -42,541 +42,250 @@
./usr/lib/libutil.so.4.1
./usr/lib/libwrap.so.1.0
./usr/lib/libz.so.1.2
-./usr/lib/perl5/DB_File.pm
-./usr/lib/perl5/Fcntl.pm
-./usr/lib/perl5/FileHandle.pm
-./usr/lib/perl5/POSIX.pm
-./usr/lib/perl5/POSIX.pod
-./usr/lib/perl5/SDBM_File.pm
-./usr/lib/perl5/Safe.pm
-./usr/lib/perl5/Socket.pm
-./usr/lib/perl5/auto/DB_File
-./usr/lib/perl5/auto/DB_File/autosplit.ix
-./usr/lib/perl5/auto/Fcntl
-./usr/lib/perl5/auto/Fcntl/autosplit.ix
-./usr/lib/perl5/auto/POSIX
-./usr/lib/perl5/auto/POSIX/abs.al
-./usr/lib/perl5/auto/POSIX/alarm.al
-./usr/lib/perl5/auto/POSIX/assert.al
-./usr/lib/perl5/auto/POSIX/atan2.al
-./usr/lib/perl5/auto/POSIX/atexit.al
-./usr/lib/perl5/auto/POSIX/atof.al
-./usr/lib/perl5/auto/POSIX/atoi.al
-./usr/lib/perl5/auto/POSIX/atol.al
-./usr/lib/perl5/auto/POSIX/autosplit.ix
-./usr/lib/perl5/auto/POSIX/bsearch.al
-./usr/lib/perl5/auto/POSIX/calloc.al
-./usr/lib/perl5/auto/POSIX/chdir.al
-./usr/lib/perl5/auto/POSIX/chmod.al
-./usr/lib/perl5/auto/POSIX/chown.al
-./usr/lib/perl5/auto/POSIX/clearerr.al
-./usr/lib/perl5/auto/POSIX/closedir.al
-./usr/lib/perl5/auto/POSIX/cos.al
-./usr/lib/perl5/auto/POSIX/creat.al
-./usr/lib/perl5/auto/POSIX/div.al
-./usr/lib/perl5/auto/POSIX/errno.al
-./usr/lib/perl5/auto/POSIX/execl.al
-./usr/lib/perl5/auto/POSIX/execle.al
-./usr/lib/perl5/auto/POSIX/execlp.al
-./usr/lib/perl5/auto/POSIX/execv.al
-./usr/lib/perl5/auto/POSIX/execve.al
-./usr/lib/perl5/auto/POSIX/execvp.al
-./usr/lib/perl5/auto/POSIX/exit.al
-./usr/lib/perl5/auto/POSIX/exp.al
-./usr/lib/perl5/auto/POSIX/fabs.al
-./usr/lib/perl5/auto/POSIX/fclose.al
-./usr/lib/perl5/auto/POSIX/fcntl.al
-./usr/lib/perl5/auto/POSIX/fdopen.al
-./usr/lib/perl5/auto/POSIX/feof.al
-./usr/lib/perl5/auto/POSIX/ferror.al
-./usr/lib/perl5/auto/POSIX/fflush.al
-./usr/lib/perl5/auto/POSIX/fgetc.al
-./usr/lib/perl5/auto/POSIX/fgetpos.al
-./usr/lib/perl5/auto/POSIX/fgets.al
-./usr/lib/perl5/auto/POSIX/fileno.al
-./usr/lib/perl5/auto/POSIX/fopen.al
-./usr/lib/perl5/auto/POSIX/fork.al
-./usr/lib/perl5/auto/POSIX/fprintf.al
-./usr/lib/perl5/auto/POSIX/fputc.al
-./usr/lib/perl5/auto/POSIX/fputs.al
-./usr/lib/perl5/auto/POSIX/fread.al
-./usr/lib/perl5/auto/POSIX/free.al
-./usr/lib/perl5/auto/POSIX/freopen.al
-./usr/lib/perl5/auto/POSIX/fscanf.al
-./usr/lib/perl5/auto/POSIX/fseek.al
-./usr/lib/perl5/auto/POSIX/fsetpos.al
-./usr/lib/perl5/auto/POSIX/fstat.al
-./usr/lib/perl5/auto/POSIX/ftell.al
-./usr/lib/perl5/auto/POSIX/fwrite.al
-./usr/lib/perl5/auto/POSIX/getc.al
-./usr/lib/perl5/auto/POSIX/getchar.al
-./usr/lib/perl5/auto/POSIX/getcwd.al
-./usr/lib/perl5/auto/POSIX/getegid.al
-./usr/lib/perl5/auto/POSIX/getenv.al
-./usr/lib/perl5/auto/POSIX/geteuid.al
-./usr/lib/perl5/auto/POSIX/getgid.al
-./usr/lib/perl5/auto/POSIX/getgrgid.al
-./usr/lib/perl5/auto/POSIX/getgrnam.al
-./usr/lib/perl5/auto/POSIX/getgroups.al
-./usr/lib/perl5/auto/POSIX/getlogin.al
-./usr/lib/perl5/auto/POSIX/getpgrp.al
-./usr/lib/perl5/auto/POSIX/getpid.al
-./usr/lib/perl5/auto/POSIX/getppid.al
-./usr/lib/perl5/auto/POSIX/getpwnam.al
-./usr/lib/perl5/auto/POSIX/getpwuid.al
-./usr/lib/perl5/auto/POSIX/gets.al
-./usr/lib/perl5/auto/POSIX/getuid.al
-./usr/lib/perl5/auto/POSIX/gmtime.al
-./usr/lib/perl5/auto/POSIX/isatty.al
-./usr/lib/perl5/auto/POSIX/kill.al
-./usr/lib/perl5/auto/POSIX/labs.al
-./usr/lib/perl5/auto/POSIX/ldiv.al
-./usr/lib/perl5/auto/POSIX/link.al
-./usr/lib/perl5/auto/POSIX/localtime.al
-./usr/lib/perl5/auto/POSIX/log.al
-./usr/lib/perl5/auto/POSIX/longjmp.al
-./usr/lib/perl5/auto/POSIX/malloc.al
-./usr/lib/perl5/auto/POSIX/memchr.al
-./usr/lib/perl5/auto/POSIX/memcmp.al
-./usr/lib/perl5/auto/POSIX/memcpy.al
-./usr/lib/perl5/auto/POSIX/memmove.al
-./usr/lib/perl5/auto/POSIX/memset.al
-./usr/lib/perl5/auto/POSIX/mkdir.al
-./usr/lib/perl5/auto/POSIX/offsetof.al
-./usr/lib/perl5/auto/POSIX/opendir.al
-./usr/lib/perl5/auto/POSIX/perror.al
-./usr/lib/perl5/auto/POSIX/pow.al
-./usr/lib/perl5/auto/POSIX/printf.al
-./usr/lib/perl5/auto/POSIX/putc.al
-./usr/lib/perl5/auto/POSIX/putchar.al
-./usr/lib/perl5/auto/POSIX/puts.al
-./usr/lib/perl5/auto/POSIX/qsort.al
-./usr/lib/perl5/auto/POSIX/raise.al
-./usr/lib/perl5/auto/POSIX/rand.al
-./usr/lib/perl5/auto/POSIX/readdir.al
-./usr/lib/perl5/auto/POSIX/realloc.al
-./usr/lib/perl5/auto/POSIX/remove.al
-./usr/lib/perl5/auto/POSIX/rename.al
-./usr/lib/perl5/auto/POSIX/rewind.al
-./usr/lib/perl5/auto/POSIX/rewinddir.al
-./usr/lib/perl5/auto/POSIX/rmdir.al
-./usr/lib/perl5/auto/POSIX/scanf.al
-./usr/lib/perl5/auto/POSIX/setgid.al
-./usr/lib/perl5/auto/POSIX/setjmp.al
-./usr/lib/perl5/auto/POSIX/setuid.al
-./usr/lib/perl5/auto/POSIX/siglongjmp.al
-./usr/lib/perl5/auto/POSIX/sigsetjmp.al
-./usr/lib/perl5/auto/POSIX/sin.al
-./usr/lib/perl5/auto/POSIX/sleep.al
-./usr/lib/perl5/auto/POSIX/sprintf.al
-./usr/lib/perl5/auto/POSIX/sqrt.al
-./usr/lib/perl5/auto/POSIX/srand.al
-./usr/lib/perl5/auto/POSIX/sscanf.al
-./usr/lib/perl5/auto/POSIX/stat.al
-./usr/lib/perl5/auto/POSIX/strcat.al
-./usr/lib/perl5/auto/POSIX/strchr.al
-./usr/lib/perl5/auto/POSIX/strcmp.al
-./usr/lib/perl5/auto/POSIX/strcpy.al
-./usr/lib/perl5/auto/POSIX/strcspn.al
-./usr/lib/perl5/auto/POSIX/strerror.al
-./usr/lib/perl5/auto/POSIX/strlen.al
-./usr/lib/perl5/auto/POSIX/strncat.al
-./usr/lib/perl5/auto/POSIX/strncmp.al
-./usr/lib/perl5/auto/POSIX/strncpy.al
-./usr/lib/perl5/auto/POSIX/stroul.al
-./usr/lib/perl5/auto/POSIX/strpbrk.al
-./usr/lib/perl5/auto/POSIX/strrchr.al
-./usr/lib/perl5/auto/POSIX/strspn.al
-./usr/lib/perl5/auto/POSIX/strstr.al
-./usr/lib/perl5/auto/POSIX/strtod.al
-./usr/lib/perl5/auto/POSIX/strtok.al
-./usr/lib/perl5/auto/POSIX/strtol.al
-./usr/lib/perl5/auto/POSIX/system.al
-./usr/lib/perl5/auto/POSIX/time.al
-./usr/lib/perl5/auto/POSIX/tmpfile.al
-./usr/lib/perl5/auto/POSIX/tolower.al
-./usr/lib/perl5/auto/POSIX/toupper.al
-./usr/lib/perl5/auto/POSIX/umask.al
-./usr/lib/perl5/auto/POSIX/ungetc.al
-./usr/lib/perl5/auto/POSIX/unlink.al
-./usr/lib/perl5/auto/POSIX/utime.al
-./usr/lib/perl5/auto/POSIX/vfprintf.al
-./usr/lib/perl5/auto/POSIX/vprintf.al
-./usr/lib/perl5/auto/POSIX/vsprintf.al
-./usr/lib/perl5/auto/POSIX/wait.al
-./usr/lib/perl5/auto/POSIX/waitpid.al
-./usr/lib/perl5/auto/Socket
-./usr/lib/perl5/auto/Socket/autosplit.ix
-./usr/lib/perl5/auto/Text
-./usr/lib/perl5/auto/Text/ParseWords
-./usr/lib/perl5/auto/Text/ParseWords/autosplit.ix
-./usr/lib/perl5/auto/Text/ParseWords/old_shellwords.al
-./usr/lib/perl5/auto/Text/ParseWords/quotewords.al
-./usr/lib/perl5/auto/Text/ParseWords/shellwords.al
./usr/lib/perl5/i386-openbsd
-./usr/lib/perl5/i386-openbsd/5.003
-./usr/lib/perl5/i386-openbsd/5.003/CORE
-./usr/lib/perl5/i386-openbsd/5.003/CORE/EXTERN.h
-./usr/lib/perl5/i386-openbsd/5.003/CORE/INTERN.h
-./usr/lib/perl5/i386-openbsd/5.003/CORE/XSUB.h
-./usr/lib/perl5/i386-openbsd/5.003/CORE/av.h
-./usr/lib/perl5/i386-openbsd/5.003/CORE/config.h
-./usr/lib/perl5/i386-openbsd/5.003/CORE/cop.h
-./usr/lib/perl5/i386-openbsd/5.003/CORE/cv.h
-./usr/lib/perl5/i386-openbsd/5.003/CORE/dosish.h
-./usr/lib/perl5/i386-openbsd/5.003/CORE/embed.h
-./usr/lib/perl5/i386-openbsd/5.003/CORE/form.h
-./usr/lib/perl5/i386-openbsd/5.003/CORE/gv.h
-./usr/lib/perl5/i386-openbsd/5.003/CORE/handy.h
-./usr/lib/perl5/i386-openbsd/5.003/CORE/hv.h
-./usr/lib/perl5/i386-openbsd/5.003/CORE/keywords.h
-./usr/lib/perl5/i386-openbsd/5.003/CORE/libperl.a
-./usr/lib/perl5/i386-openbsd/5.003/CORE/mg.h
-./usr/lib/perl5/i386-openbsd/5.003/CORE/op.h
-./usr/lib/perl5/i386-openbsd/5.003/CORE/opcode.h
-./usr/lib/perl5/i386-openbsd/5.003/CORE/patchlevel.h
-./usr/lib/perl5/i386-openbsd/5.003/CORE/perl.h
-./usr/lib/perl5/i386-openbsd/5.003/CORE/perly.h
-./usr/lib/perl5/i386-openbsd/5.003/CORE/pp.h
-./usr/lib/perl5/i386-openbsd/5.003/CORE/proto.h
-./usr/lib/perl5/i386-openbsd/5.003/CORE/regcomp.h
-./usr/lib/perl5/i386-openbsd/5.003/CORE/regexp.h
-./usr/lib/perl5/i386-openbsd/5.003/CORE/scope.h
-./usr/lib/perl5/i386-openbsd/5.003/CORE/sv.h
-./usr/lib/perl5/i386-openbsd/5.003/CORE/unixish.h
-./usr/lib/perl5/i386-openbsd/5.003/CORE/util.h
-./usr/lib/perl5/i386-openbsd/5.003/Config.pm
-./usr/lib/perl5/i386-openbsd/5.003/a.out.ph
-./usr/lib/perl5/i386-openbsd/5.003/ar.ph
-./usr/lib/perl5/i386-openbsd/5.003/arpa
-./usr/lib/perl5/i386-openbsd/5.003/arpa/ftp.ph
-./usr/lib/perl5/i386-openbsd/5.003/arpa/inet.ph
-./usr/lib/perl5/i386-openbsd/5.003/arpa/nameser.ph
-./usr/lib/perl5/i386-openbsd/5.003/arpa/telnet.ph
-./usr/lib/perl5/i386-openbsd/5.003/arpa/tftp.ph
-./usr/lib/perl5/i386-openbsd/5.003/assert.ph
-./usr/lib/perl5/i386-openbsd/5.003/auto
-./usr/lib/perl5/i386-openbsd/5.003/auto/DB_File
-./usr/lib/perl5/i386-openbsd/5.003/auto/DB_File/DB_File.bs
-./usr/lib/perl5/i386-openbsd/5.003/auto/DB_File/DB_File.so
-./usr/lib/perl5/i386-openbsd/5.003/auto/DynaLoader
-./usr/lib/perl5/i386-openbsd/5.003/auto/DynaLoader/DynaLoader.a
-./usr/lib/perl5/i386-openbsd/5.003/auto/DynaLoader/extralibs.ld
-./usr/lib/perl5/i386-openbsd/5.003/auto/Fcntl
-./usr/lib/perl5/i386-openbsd/5.003/auto/Fcntl/Fcntl.bs
-./usr/lib/perl5/i386-openbsd/5.003/auto/Fcntl/Fcntl.so
-./usr/lib/perl5/i386-openbsd/5.003/auto/FileHandle
-./usr/lib/perl5/i386-openbsd/5.003/auto/FileHandle/FileHandle.bs
-./usr/lib/perl5/i386-openbsd/5.003/auto/FileHandle/FileHandle.so
-./usr/lib/perl5/i386-openbsd/5.003/auto/POSIX
-./usr/lib/perl5/i386-openbsd/5.003/auto/POSIX/POSIX.bs
-./usr/lib/perl5/i386-openbsd/5.003/auto/POSIX/POSIX.so
-./usr/lib/perl5/i386-openbsd/5.003/auto/SDBM_File
-./usr/lib/perl5/i386-openbsd/5.003/auto/SDBM_File/SDBM_File.bs
-./usr/lib/perl5/i386-openbsd/5.003/auto/SDBM_File/SDBM_File.so
-./usr/lib/perl5/i386-openbsd/5.003/auto/Safe
-./usr/lib/perl5/i386-openbsd/5.003/auto/Safe/Safe.bs
-./usr/lib/perl5/i386-openbsd/5.003/auto/Safe/Safe.so
-./usr/lib/perl5/i386-openbsd/5.003/auto/Socket
-./usr/lib/perl5/i386-openbsd/5.003/auto/Socket/Socket.bs
-./usr/lib/perl5/i386-openbsd/5.003/auto/Socket/Socket.so
-./usr/lib/perl5/i386-openbsd/5.003/auto/Text
-./usr/lib/perl5/i386-openbsd/5.003/auto/Text/ParseWords
-./usr/lib/perl5/i386-openbsd/5.003/bitstring.ph
-./usr/lib/perl5/i386-openbsd/5.003/blf.ph
-./usr/lib/perl5/i386-openbsd/5.003/bm.ph
-./usr/lib/perl5/i386-openbsd/5.003/com_err.ph
-./usr/lib/perl5/i386-openbsd/5.003/cpio.ph
-./usr/lib/perl5/i386-openbsd/5.003/ctype.ph
-./usr/lib/perl5/i386-openbsd/5.003/curses.ph
-./usr/lib/perl5/i386-openbsd/5.003/db.ph
-./usr/lib/perl5/i386-openbsd/5.003/des.ph
-./usr/lib/perl5/i386-openbsd/5.003/dirent.ph
-./usr/lib/perl5/i386-openbsd/5.003/disktab.ph
-./usr/lib/perl5/i386-openbsd/5.003/dlfcn.ph
-./usr/lib/perl5/i386-openbsd/5.003/elf_abi.ph
-./usr/lib/perl5/i386-openbsd/5.003/err.ph
-./usr/lib/perl5/i386-openbsd/5.003/errno.ph
-./usr/lib/perl5/i386-openbsd/5.003/eti.ph
-./usr/lib/perl5/i386-openbsd/5.003/fcntl.ph
-./usr/lib/perl5/i386-openbsd/5.003/float.ph
-./usr/lib/perl5/i386-openbsd/5.003/fnmatch.ph
-./usr/lib/perl5/i386-openbsd/5.003/form.ph
-./usr/lib/perl5/i386-openbsd/5.003/frame.ph
-./usr/lib/perl5/i386-openbsd/5.003/fstab.ph
-./usr/lib/perl5/i386-openbsd/5.003/fts.ph
-./usr/lib/perl5/i386-openbsd/5.003/glob.ph
-./usr/lib/perl5/i386-openbsd/5.003/gmp.ph
-./usr/lib/perl5/i386-openbsd/5.003/grp.ph
-./usr/lib/perl5/i386-openbsd/5.003/histedit.ph
-./usr/lib/perl5/i386-openbsd/5.003/ieeefp.ph
-./usr/lib/perl5/i386-openbsd/5.003/inttypes.ph
-./usr/lib/perl5/i386-openbsd/5.003/iso646.ph
-./usr/lib/perl5/i386-openbsd/5.003/kvm.ph
-./usr/lib/perl5/i386-openbsd/5.003/langinfo.ph
-./usr/lib/perl5/i386-openbsd/5.003/libgen.ph
-./usr/lib/perl5/i386-openbsd/5.003/limits.ph
-./usr/lib/perl5/i386-openbsd/5.003/link.ph
-./usr/lib/perl5/i386-openbsd/5.003/locale.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine
-./usr/lib/perl5/i386-openbsd/5.003/machine/ansi.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/apmvar.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/asm.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/biosvar.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/bus.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/cdefs.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/conf.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/cpu.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/cpufunc.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/cputypes.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/db_machdep.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/disklabel.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/endian.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/exec.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/float.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/frame.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/freebsd_machdep.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/gdt.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/ieeefp.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/intr.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/ioctl_fd.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/joystick.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/limits.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/linux_machdep.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/mouse.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/npx.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/param.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/pcb.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/pccons.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/pctr.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/pcvt_ioctl.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/pio.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/pmap.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/proc.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/profile.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/psl.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/pte.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/ptrace.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/reg.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/segments.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/setjmp.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/signal.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/specialreg.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/spkr.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/stdarg.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/svr4_machdep.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/sysarch.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/trap.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/tss.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/types.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/varargs.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/vm86.ph
-./usr/lib/perl5/i386-openbsd/5.003/machine/vmparam.ph
-./usr/lib/perl5/i386-openbsd/5.003/malloc.ph
-./usr/lib/perl5/i386-openbsd/5.003/math.ph
-./usr/lib/perl5/i386-openbsd/5.003/md4.ph
-./usr/lib/perl5/i386-openbsd/5.003/md5.ph
-./usr/lib/perl5/i386-openbsd/5.003/memory.ph
-./usr/lib/perl5/i386-openbsd/5.003/menu.ph
-./usr/lib/perl5/i386-openbsd/5.003/mpool.ph
-./usr/lib/perl5/i386-openbsd/5.003/ndbm.ph
-./usr/lib/perl5/i386-openbsd/5.003/net
-./usr/lib/perl5/i386-openbsd/5.003/net/bpf.ph
-./usr/lib/perl5/i386-openbsd/5.003/net/bpfdesc.ph
-./usr/lib/perl5/i386-openbsd/5.003/net/encap.ph
-./usr/lib/perl5/i386-openbsd/5.003/net/if.ph
-./usr/lib/perl5/i386-openbsd/5.003/net/if_arp.ph
-./usr/lib/perl5/i386-openbsd/5.003/net/if_atm.ph
-./usr/lib/perl5/i386-openbsd/5.003/net/if_dl.ph
-./usr/lib/perl5/i386-openbsd/5.003/net/if_fddi.ph
-./usr/lib/perl5/i386-openbsd/5.003/net/if_llc.ph
-./usr/lib/perl5/i386-openbsd/5.003/net/if_ppp.ph
-./usr/lib/perl5/i386-openbsd/5.003/net/if_pppvar.ph
-./usr/lib/perl5/i386-openbsd/5.003/net/if_slvar.ph
-./usr/lib/perl5/i386-openbsd/5.003/net/if_stripvar.ph
-./usr/lib/perl5/i386-openbsd/5.003/net/if_tun.ph
-./usr/lib/perl5/i386-openbsd/5.003/net/if_types.ph
-./usr/lib/perl5/i386-openbsd/5.003/net/netisr.ph
-./usr/lib/perl5/i386-openbsd/5.003/net/pfkeyv2.ph
-./usr/lib/perl5/i386-openbsd/5.003/net/ppp-comp.ph
-./usr/lib/perl5/i386-openbsd/5.003/net/ppp_defs.ph
-./usr/lib/perl5/i386-openbsd/5.003/net/radix.ph
-./usr/lib/perl5/i386-openbsd/5.003/net/raw_cb.ph
-./usr/lib/perl5/i386-openbsd/5.003/net/route.ph
-./usr/lib/perl5/i386-openbsd/5.003/net/slcompress.ph
-./usr/lib/perl5/i386-openbsd/5.003/net/slip.ph
-./usr/lib/perl5/i386-openbsd/5.003/net/zlib.ph
-./usr/lib/perl5/i386-openbsd/5.003/netdb.ph
-./usr/lib/perl5/i386-openbsd/5.003/netgroup.ph
-./usr/lib/perl5/i386-openbsd/5.003/nl_types.ph
-./usr/lib/perl5/i386-openbsd/5.003/nlist.ph
-./usr/lib/perl5/i386-openbsd/5.003/ocurses.ph
-./usr/lib/perl5/i386-openbsd/5.003/olf_abi.ph
-./usr/lib/perl5/i386-openbsd/5.003/panel.ph
-./usr/lib/perl5/i386-openbsd/5.003/paths.ph
-./usr/lib/perl5/i386-openbsd/5.003/pcap-namedb.ph
-./usr/lib/perl5/i386-openbsd/5.003/pcap.ph
-./usr/lib/perl5/i386-openbsd/5.003/poll.ph
-./usr/lib/perl5/i386-openbsd/5.003/protocols
-./usr/lib/perl5/i386-openbsd/5.003/protocols/dumprestore.ph
-./usr/lib/perl5/i386-openbsd/5.003/protocols/routed.ph
-./usr/lib/perl5/i386-openbsd/5.003/protocols/rwhod.ph
-./usr/lib/perl5/i386-openbsd/5.003/protocols/talkd.ph
-./usr/lib/perl5/i386-openbsd/5.003/protocols/timed.ph
-./usr/lib/perl5/i386-openbsd/5.003/pwd.ph
-./usr/lib/perl5/i386-openbsd/5.003/ranlib.ph
-./usr/lib/perl5/i386-openbsd/5.003/re_comp.ph
-./usr/lib/perl5/i386-openbsd/5.003/regex.ph
-./usr/lib/perl5/i386-openbsd/5.003/regexp.ph
-./usr/lib/perl5/i386-openbsd/5.003/resolv.ph
-./usr/lib/perl5/i386-openbsd/5.003/rmd160.ph
-./usr/lib/perl5/i386-openbsd/5.003/scsi.ph
-./usr/lib/perl5/i386-openbsd/5.003/search.ph
-./usr/lib/perl5/i386-openbsd/5.003/setjmp.ph
-./usr/lib/perl5/i386-openbsd/5.003/sgtty.ph
-./usr/lib/perl5/i386-openbsd/5.003/sha1.ph
-./usr/lib/perl5/i386-openbsd/5.003/signal.ph
-./usr/lib/perl5/i386-openbsd/5.003/skey.ph
-./usr/lib/perl5/i386-openbsd/5.003/stab.ph
-./usr/lib/perl5/i386-openbsd/5.003/stdarg.ph
-./usr/lib/perl5/i386-openbsd/5.003/stddef.ph
-./usr/lib/perl5/i386-openbsd/5.003/stdio.ph
-./usr/lib/perl5/i386-openbsd/5.003/stdlib.ph
-./usr/lib/perl5/i386-openbsd/5.003/string.ph
-./usr/lib/perl5/i386-openbsd/5.003/strings.ph
-./usr/lib/perl5/i386-openbsd/5.003/struct.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys
-./usr/lib/perl5/i386-openbsd/5.003/sys/acct.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/audioio.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/buf.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/callout.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/cdefs.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/cdio.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/chio.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/clist.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/conf.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/core.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/device.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/dir.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/dirent.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/disk.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/disklabel.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/dkbad.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/dkio.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/dkstat.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/dmap.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/domain.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/endian.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/errno.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/exec.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/exec_aout.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/exec_ecoff.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/exec_elf.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/exec_olf.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/exec_script.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/extent.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/fcntl.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/file.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/filedesc.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/filio.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/gmon.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/ioccom.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/ioctl.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/ioctl_compat.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/ipc.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/kcore.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/kernel.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/ktrace.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/lkm.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/localedef.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/lock.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/lockf.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/malloc.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/map.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/mbuf.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/md5k.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/mman.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/mount.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/msg.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/msgbuf.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/mtio.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/namei.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/param.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/pipe.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/poll.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/proc.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/protosw.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/ptrace.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/queue.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/reboot.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/resource.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/resourcevar.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/scanio.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/scsiio.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/select.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/sem.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/shm.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/siginfo.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/signal.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/signalvar.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/simplelock.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/socket.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/socketvar.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/sockio.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/stat.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/syscall.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/syscallargs.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/sysctl.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/syslimits.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/syslog.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/systm.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/tablet.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/termios.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/time.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/timeb.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/times.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/timex.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/tprintf.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/trace.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/tty.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/ttychars.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/ttycom.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/ttydefaults.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/ttydev.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/types.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/ucred.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/uio.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/un.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/unistd.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/unpcb.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/user.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/utsname.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/vadvise.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/vcmd.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/vlimit.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/vmmeter.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/vnode.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/vnode_if.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/vsio.ph
-./usr/lib/perl5/i386-openbsd/5.003/sys/wait.ph
-./usr/lib/perl5/i386-openbsd/5.003/sysexits.ph
-./usr/lib/perl5/i386-openbsd/5.003/syslog.ph
-./usr/lib/perl5/i386-openbsd/5.003/tar.ph
-./usr/lib/perl5/i386-openbsd/5.003/tcpd.ph
-./usr/lib/perl5/i386-openbsd/5.003/term.ph
-./usr/lib/perl5/i386-openbsd/5.003/termios.ph
-./usr/lib/perl5/i386-openbsd/5.003/time.ph
-./usr/lib/perl5/i386-openbsd/5.003/ttyent.ph
-./usr/lib/perl5/i386-openbsd/5.003/tzfile.ph
-./usr/lib/perl5/i386-openbsd/5.003/unctrl.ph
-./usr/lib/perl5/i386-openbsd/5.003/unistd.ph
-./usr/lib/perl5/i386-openbsd/5.003/util.ph
-./usr/lib/perl5/i386-openbsd/5.003/utime.ph
-./usr/lib/perl5/i386-openbsd/5.003/utmp.ph
-./usr/lib/perl5/i386-openbsd/5.003/varargs.ph
-./usr/lib/perl5/i386-openbsd/5.003/vis.ph
-./usr/lib/perl5/i386-openbsd/5.003/zconf.ph
-./usr/lib/perl5/i386-openbsd/5.003/zlib.ph
+./usr/lib/perl5/i386-openbsd/5.00404
+./usr/lib/perl5/i386-openbsd/5.00404/CORE
+./usr/lib/perl5/i386-openbsd/5.00404/CORE/EXTERN.h
+./usr/lib/perl5/i386-openbsd/5.00404/CORE/INTERN.h
+./usr/lib/perl5/i386-openbsd/5.00404/CORE/XSUB.h
+./usr/lib/perl5/i386-openbsd/5.00404/CORE/av.h
+./usr/lib/perl5/i386-openbsd/5.00404/CORE/config.h
+./usr/lib/perl5/i386-openbsd/5.00404/CORE/cop.h
+./usr/lib/perl5/i386-openbsd/5.00404/CORE/cv.h
+./usr/lib/perl5/i386-openbsd/5.00404/CORE/dosish.h
+./usr/lib/perl5/i386-openbsd/5.00404/CORE/embed.h
+./usr/lib/perl5/i386-openbsd/5.00404/CORE/form.h
+./usr/lib/perl5/i386-openbsd/5.00404/CORE/gv.h
+./usr/lib/perl5/i386-openbsd/5.00404/CORE/handy.h
+./usr/lib/perl5/i386-openbsd/5.00404/CORE/hv.h
+./usr/lib/perl5/i386-openbsd/5.00404/CORE/keywords.h
+./usr/lib/perl5/i386-openbsd/5.00404/CORE/libperl.a
+./usr/lib/perl5/i386-openbsd/5.00404/CORE/mg.h
+./usr/lib/perl5/i386-openbsd/5.00404/CORE/nostdio.h
+./usr/lib/perl5/i386-openbsd/5.00404/CORE/op.h
+./usr/lib/perl5/i386-openbsd/5.00404/CORE/opcode.h
+./usr/lib/perl5/i386-openbsd/5.00404/CORE/patchlevel.h
+./usr/lib/perl5/i386-openbsd/5.00404/CORE/perl.h
+./usr/lib/perl5/i386-openbsd/5.00404/CORE/perlio.h
+./usr/lib/perl5/i386-openbsd/5.00404/CORE/perlsdio.h
+./usr/lib/perl5/i386-openbsd/5.00404/CORE/perlsfio.h
+./usr/lib/perl5/i386-openbsd/5.00404/CORE/perly.h
+./usr/lib/perl5/i386-openbsd/5.00404/CORE/pp.h
+./usr/lib/perl5/i386-openbsd/5.00404/CORE/proto.h
+./usr/lib/perl5/i386-openbsd/5.00404/CORE/regcomp.h
+./usr/lib/perl5/i386-openbsd/5.00404/CORE/regexp.h
+./usr/lib/perl5/i386-openbsd/5.00404/CORE/scope.h
+./usr/lib/perl5/i386-openbsd/5.00404/CORE/sv.h
+./usr/lib/perl5/i386-openbsd/5.00404/CORE/unixish.h
+./usr/lib/perl5/i386-openbsd/5.00404/CORE/util.h
+./usr/lib/perl5/i386-openbsd/5.00404/Config.pm
+./usr/lib/perl5/i386-openbsd/5.00404/DB_File.pm
+./usr/lib/perl5/i386-openbsd/5.00404/DynaLoader.pm
+./usr/lib/perl5/i386-openbsd/5.00404/Fcntl.pm
+./usr/lib/perl5/i386-openbsd/5.00404/FileHandle.pm
+./usr/lib/perl5/i386-openbsd/5.00404/IO
+./usr/lib/perl5/i386-openbsd/5.00404/IO.pm
+./usr/lib/perl5/i386-openbsd/5.00404/IO/File.pm
+./usr/lib/perl5/i386-openbsd/5.00404/IO/Handle.pm
+./usr/lib/perl5/i386-openbsd/5.00404/IO/Pipe.pm
+./usr/lib/perl5/i386-openbsd/5.00404/IO/Seekable.pm
+./usr/lib/perl5/i386-openbsd/5.00404/IO/Select.pm
+./usr/lib/perl5/i386-openbsd/5.00404/IO/Socket.pm
+./usr/lib/perl5/i386-openbsd/5.00404/NDBM_File.pm
+./usr/lib/perl5/i386-openbsd/5.00404/Opcode.pm
+./usr/lib/perl5/i386-openbsd/5.00404/POSIX.pm
+./usr/lib/perl5/i386-openbsd/5.00404/POSIX.pod
+./usr/lib/perl5/i386-openbsd/5.00404/SDBM_File.pm
+./usr/lib/perl5/i386-openbsd/5.00404/Safe.pm
+./usr/lib/perl5/i386-openbsd/5.00404/Socket.pm
+./usr/lib/perl5/i386-openbsd/5.00404/auto
+./usr/lib/perl5/i386-openbsd/5.00404/auto/DB_File
+./usr/lib/perl5/i386-openbsd/5.00404/auto/DB_File/DB_File.bs
+./usr/lib/perl5/i386-openbsd/5.00404/auto/DB_File/DB_File.so
+./usr/lib/perl5/i386-openbsd/5.00404/auto/DB_File/autosplit.ix
+./usr/lib/perl5/i386-openbsd/5.00404/auto/DynaLoader
+./usr/lib/perl5/i386-openbsd/5.00404/auto/DynaLoader/DynaLoader.a
+./usr/lib/perl5/i386-openbsd/5.00404/auto/DynaLoader/autosplit.ix
+./usr/lib/perl5/i386-openbsd/5.00404/auto/DynaLoader/dl_expandspec.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/DynaLoader/dl_find_symbol_anywhere.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/DynaLoader/dl_findfile.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/DynaLoader/extralibs.ld
+./usr/lib/perl5/i386-openbsd/5.00404/auto/Fcntl
+./usr/lib/perl5/i386-openbsd/5.00404/auto/Fcntl/Fcntl.bs
+./usr/lib/perl5/i386-openbsd/5.00404/auto/Fcntl/Fcntl.so
+./usr/lib/perl5/i386-openbsd/5.00404/auto/IO
+./usr/lib/perl5/i386-openbsd/5.00404/auto/IO/IO.bs
+./usr/lib/perl5/i386-openbsd/5.00404/auto/IO/IO.so
+./usr/lib/perl5/i386-openbsd/5.00404/auto/NDBM_File
+./usr/lib/perl5/i386-openbsd/5.00404/auto/NDBM_File/NDBM_File.bs
+./usr/lib/perl5/i386-openbsd/5.00404/auto/NDBM_File/NDBM_File.so
+./usr/lib/perl5/i386-openbsd/5.00404/auto/Opcode
+./usr/lib/perl5/i386-openbsd/5.00404/auto/Opcode/Opcode.bs
+./usr/lib/perl5/i386-openbsd/5.00404/auto/Opcode/Opcode.so
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/POSIX.bs
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/POSIX.so
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/abs.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/alarm.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/assert.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/atan2.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/atexit.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/atof.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/atoi.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/atol.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/autosplit.ix
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/bsearch.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/calloc.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/chdir.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/chmod.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/chown.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/clearerr.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/closedir.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/cos.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/creat.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/div.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/errno.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/execl.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/execle.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/execlp.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/execv.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/execve.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/execvp.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/exit.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/exp.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/fabs.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/fclose.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/fcntl.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/fdopen.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/feof.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/ferror.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/fflush.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/fgetc.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/fgetpos.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/fgets.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/fileno.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/fopen.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/fork.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/fprintf.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/fputc.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/fputs.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/fread.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/free.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/freopen.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/fscanf.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/fseek.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/fsetpos.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/fstat.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/ftell.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/fwrite.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/getc.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/getchar.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/getcwd.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/getegid.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/getenv.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/geteuid.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/getgid.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/getgrgid.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/getgrnam.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/getgroups.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/getlogin.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/getpgrp.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/getpid.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/getppid.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/getpwnam.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/getpwuid.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/gets.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/getuid.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/gmtime.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/isatty.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/kill.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/labs.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/ldiv.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/link.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/localtime.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/log.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/longjmp.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/malloc.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/memchr.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/memcmp.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/memcpy.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/memmove.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/memset.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/mkdir.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/offsetof.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/opendir.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/perror.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/pow.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/printf.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/putc.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/putchar.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/puts.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/qsort.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/raise.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/rand.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/readdir.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/realloc.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/remove.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/rename.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/rewind.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/rewinddir.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/rmdir.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/scanf.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/setgid.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/setjmp.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/setuid.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/siglongjmp.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/sigsetjmp.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/sin.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/sleep.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/sprintf.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/sqrt.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/srand.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/sscanf.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/stat.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/strcat.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/strchr.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/strcmp.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/strcpy.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/strcspn.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/strerror.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/strlen.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/strncat.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/strncmp.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/strncpy.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/strpbrk.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/strrchr.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/strspn.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/strstr.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/strtok.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/system.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/time.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/tmpfile.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/tolower.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/toupper.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/umask.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/ungetc.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/unlink.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/utime.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/vfprintf.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/vprintf.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/vsprintf.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/wait.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/POSIX/waitpid.al
+./usr/lib/perl5/i386-openbsd/5.00404/auto/SDBM_File
+./usr/lib/perl5/i386-openbsd/5.00404/auto/SDBM_File/SDBM_File.bs
+./usr/lib/perl5/i386-openbsd/5.00404/auto/SDBM_File/SDBM_File.so
+./usr/lib/perl5/i386-openbsd/5.00404/auto/Socket
+./usr/lib/perl5/i386-openbsd/5.00404/auto/Socket/Socket.bs
+./usr/lib/perl5/i386-openbsd/5.00404/auto/Socket/Socket.so
+./usr/lib/perl5/i386-openbsd/5.00404/auto/Text
+./usr/lib/perl5/i386-openbsd/5.00404/auto/Text/ParseWords
+./usr/lib/perl5/i386-openbsd/5.00404/auto/sdbm
+./usr/lib/perl5/i386-openbsd/5.00404/auto/sdbm/extralibs.ld
+./usr/lib/perl5/i386-openbsd/5.00404/ops.pm
+./usr/lib/perl5/i386-openbsd/5.00404/overload.pm
+./usr/lib/perl5/i386-openbsd/5.00404/pod
+./usr/lib/perl5/i386-openbsd/5.00404/pod/perldiag.pod
./usr/lib/perl5/site_perl/i386-openbsd
./usr/libexec/ld.so
./usr/lkm/ap.o
diff --git a/distrib/sets/lists/base/md.mvme68k b/distrib/sets/lists/base/md.mvme68k
index ed2a47bb862..c31ca9f4c18 100644
--- a/distrib/sets/lists/base/md.mvme68k
+++ b/distrib/sets/lists/base/md.mvme68k
@@ -34,521 +34,6 @@
./usr/lib/libutil.so.4.1
./usr/lib/libwrap.so.1.0
./usr/lib/libz.so.1.2
-./usr/lib/perl5/DB_File.pm
-./usr/lib/perl5/Fcntl.pm
-./usr/lib/perl5/FileHandle.pm
-./usr/lib/perl5/POSIX.pm
-./usr/lib/perl5/POSIX.pod
-./usr/lib/perl5/SDBM_File.pm
-./usr/lib/perl5/Safe.pm
-./usr/lib/perl5/Socket.pm
-./usr/lib/perl5/auto/DB_File
-./usr/lib/perl5/auto/DB_File/autosplit.ix
-./usr/lib/perl5/auto/Fcntl
-./usr/lib/perl5/auto/Fcntl/autosplit.ix
-./usr/lib/perl5/auto/POSIX
-./usr/lib/perl5/auto/POSIX/abs.al
-./usr/lib/perl5/auto/POSIX/alarm.al
-./usr/lib/perl5/auto/POSIX/assert.al
-./usr/lib/perl5/auto/POSIX/atan2.al
-./usr/lib/perl5/auto/POSIX/atexit.al
-./usr/lib/perl5/auto/POSIX/atof.al
-./usr/lib/perl5/auto/POSIX/atoi.al
-./usr/lib/perl5/auto/POSIX/atol.al
-./usr/lib/perl5/auto/POSIX/autosplit.ix
-./usr/lib/perl5/auto/POSIX/bsearch.al
-./usr/lib/perl5/auto/POSIX/calloc.al
-./usr/lib/perl5/auto/POSIX/chdir.al
-./usr/lib/perl5/auto/POSIX/chmod.al
-./usr/lib/perl5/auto/POSIX/chown.al
-./usr/lib/perl5/auto/POSIX/clearerr.al
-./usr/lib/perl5/auto/POSIX/closedir.al
-./usr/lib/perl5/auto/POSIX/cos.al
-./usr/lib/perl5/auto/POSIX/creat.al
-./usr/lib/perl5/auto/POSIX/div.al
-./usr/lib/perl5/auto/POSIX/errno.al
-./usr/lib/perl5/auto/POSIX/execl.al
-./usr/lib/perl5/auto/POSIX/execle.al
-./usr/lib/perl5/auto/POSIX/execlp.al
-./usr/lib/perl5/auto/POSIX/execv.al
-./usr/lib/perl5/auto/POSIX/execve.al
-./usr/lib/perl5/auto/POSIX/execvp.al
-./usr/lib/perl5/auto/POSIX/exit.al
-./usr/lib/perl5/auto/POSIX/exp.al
-./usr/lib/perl5/auto/POSIX/fabs.al
-./usr/lib/perl5/auto/POSIX/fclose.al
-./usr/lib/perl5/auto/POSIX/fcntl.al
-./usr/lib/perl5/auto/POSIX/fdopen.al
-./usr/lib/perl5/auto/POSIX/feof.al
-./usr/lib/perl5/auto/POSIX/ferror.al
-./usr/lib/perl5/auto/POSIX/fflush.al
-./usr/lib/perl5/auto/POSIX/fgetc.al
-./usr/lib/perl5/auto/POSIX/fgetpos.al
-./usr/lib/perl5/auto/POSIX/fgets.al
-./usr/lib/perl5/auto/POSIX/fileno.al
-./usr/lib/perl5/auto/POSIX/fopen.al
-./usr/lib/perl5/auto/POSIX/fork.al
-./usr/lib/perl5/auto/POSIX/fprintf.al
-./usr/lib/perl5/auto/POSIX/fputc.al
-./usr/lib/perl5/auto/POSIX/fputs.al
-./usr/lib/perl5/auto/POSIX/fread.al
-./usr/lib/perl5/auto/POSIX/free.al
-./usr/lib/perl5/auto/POSIX/freopen.al
-./usr/lib/perl5/auto/POSIX/fscanf.al
-./usr/lib/perl5/auto/POSIX/fseek.al
-./usr/lib/perl5/auto/POSIX/fsetpos.al
-./usr/lib/perl5/auto/POSIX/fstat.al
-./usr/lib/perl5/auto/POSIX/ftell.al
-./usr/lib/perl5/auto/POSIX/fwrite.al
-./usr/lib/perl5/auto/POSIX/getc.al
-./usr/lib/perl5/auto/POSIX/getchar.al
-./usr/lib/perl5/auto/POSIX/getcwd.al
-./usr/lib/perl5/auto/POSIX/getegid.al
-./usr/lib/perl5/auto/POSIX/getenv.al
-./usr/lib/perl5/auto/POSIX/geteuid.al
-./usr/lib/perl5/auto/POSIX/getgid.al
-./usr/lib/perl5/auto/POSIX/getgrgid.al
-./usr/lib/perl5/auto/POSIX/getgrnam.al
-./usr/lib/perl5/auto/POSIX/getgroups.al
-./usr/lib/perl5/auto/POSIX/getlogin.al
-./usr/lib/perl5/auto/POSIX/getpgrp.al
-./usr/lib/perl5/auto/POSIX/getpid.al
-./usr/lib/perl5/auto/POSIX/getppid.al
-./usr/lib/perl5/auto/POSIX/getpwnam.al
-./usr/lib/perl5/auto/POSIX/getpwuid.al
-./usr/lib/perl5/auto/POSIX/gets.al
-./usr/lib/perl5/auto/POSIX/getuid.al
-./usr/lib/perl5/auto/POSIX/gmtime.al
-./usr/lib/perl5/auto/POSIX/isatty.al
-./usr/lib/perl5/auto/POSIX/kill.al
-./usr/lib/perl5/auto/POSIX/labs.al
-./usr/lib/perl5/auto/POSIX/ldiv.al
-./usr/lib/perl5/auto/POSIX/link.al
-./usr/lib/perl5/auto/POSIX/localtime.al
-./usr/lib/perl5/auto/POSIX/log.al
-./usr/lib/perl5/auto/POSIX/longjmp.al
-./usr/lib/perl5/auto/POSIX/malloc.al
-./usr/lib/perl5/auto/POSIX/memchr.al
-./usr/lib/perl5/auto/POSIX/memcmp.al
-./usr/lib/perl5/auto/POSIX/memcpy.al
-./usr/lib/perl5/auto/POSIX/memmove.al
-./usr/lib/perl5/auto/POSIX/memset.al
-./usr/lib/perl5/auto/POSIX/mkdir.al
-./usr/lib/perl5/auto/POSIX/offsetof.al
-./usr/lib/perl5/auto/POSIX/opendir.al
-./usr/lib/perl5/auto/POSIX/perror.al
-./usr/lib/perl5/auto/POSIX/pow.al
-./usr/lib/perl5/auto/POSIX/printf.al
-./usr/lib/perl5/auto/POSIX/putc.al
-./usr/lib/perl5/auto/POSIX/putchar.al
-./usr/lib/perl5/auto/POSIX/puts.al
-./usr/lib/perl5/auto/POSIX/qsort.al
-./usr/lib/perl5/auto/POSIX/raise.al
-./usr/lib/perl5/auto/POSIX/rand.al
-./usr/lib/perl5/auto/POSIX/readdir.al
-./usr/lib/perl5/auto/POSIX/realloc.al
-./usr/lib/perl5/auto/POSIX/remove.al
-./usr/lib/perl5/auto/POSIX/rename.al
-./usr/lib/perl5/auto/POSIX/rewind.al
-./usr/lib/perl5/auto/POSIX/rewinddir.al
-./usr/lib/perl5/auto/POSIX/rmdir.al
-./usr/lib/perl5/auto/POSIX/scanf.al
-./usr/lib/perl5/auto/POSIX/setgid.al
-./usr/lib/perl5/auto/POSIX/setjmp.al
-./usr/lib/perl5/auto/POSIX/setuid.al
-./usr/lib/perl5/auto/POSIX/siglongjmp.al
-./usr/lib/perl5/auto/POSIX/sigsetjmp.al
-./usr/lib/perl5/auto/POSIX/sin.al
-./usr/lib/perl5/auto/POSIX/sleep.al
-./usr/lib/perl5/auto/POSIX/sprintf.al
-./usr/lib/perl5/auto/POSIX/sqrt.al
-./usr/lib/perl5/auto/POSIX/srand.al
-./usr/lib/perl5/auto/POSIX/sscanf.al
-./usr/lib/perl5/auto/POSIX/stat.al
-./usr/lib/perl5/auto/POSIX/strcat.al
-./usr/lib/perl5/auto/POSIX/strchr.al
-./usr/lib/perl5/auto/POSIX/strcmp.al
-./usr/lib/perl5/auto/POSIX/strcpy.al
-./usr/lib/perl5/auto/POSIX/strcspn.al
-./usr/lib/perl5/auto/POSIX/strerror.al
-./usr/lib/perl5/auto/POSIX/strlen.al
-./usr/lib/perl5/auto/POSIX/strncat.al
-./usr/lib/perl5/auto/POSIX/strncmp.al
-./usr/lib/perl5/auto/POSIX/strncpy.al
-./usr/lib/perl5/auto/POSIX/stroul.al
-./usr/lib/perl5/auto/POSIX/strpbrk.al
-./usr/lib/perl5/auto/POSIX/strrchr.al
-./usr/lib/perl5/auto/POSIX/strspn.al
-./usr/lib/perl5/auto/POSIX/strstr.al
-./usr/lib/perl5/auto/POSIX/strtod.al
-./usr/lib/perl5/auto/POSIX/strtok.al
-./usr/lib/perl5/auto/POSIX/strtol.al
-./usr/lib/perl5/auto/POSIX/system.al
-./usr/lib/perl5/auto/POSIX/time.al
-./usr/lib/perl5/auto/POSIX/tmpfile.al
-./usr/lib/perl5/auto/POSIX/tolower.al
-./usr/lib/perl5/auto/POSIX/toupper.al
-./usr/lib/perl5/auto/POSIX/umask.al
-./usr/lib/perl5/auto/POSIX/ungetc.al
-./usr/lib/perl5/auto/POSIX/unlink.al
-./usr/lib/perl5/auto/POSIX/utime.al
-./usr/lib/perl5/auto/POSIX/vfprintf.al
-./usr/lib/perl5/auto/POSIX/vprintf.al
-./usr/lib/perl5/auto/POSIX/vsprintf.al
-./usr/lib/perl5/auto/POSIX/wait.al
-./usr/lib/perl5/auto/POSIX/waitpid.al
-./usr/lib/perl5/auto/Socket
-./usr/lib/perl5/auto/Socket/autosplit.ix
-./usr/lib/perl5/auto/Text
-./usr/lib/perl5/auto/Text/ParseWords
-./usr/lib/perl5/auto/Text/ParseWords/autosplit.ix
-./usr/lib/perl5/auto/Text/ParseWords/old_shellwords.al
-./usr/lib/perl5/auto/Text/ParseWords/quotewords.al
-./usr/lib/perl5/auto/Text/ParseWords/shellwords.al
-./usr/lib/perl5/m68k-openbsd
-./usr/lib/perl5/m68k-openbsd/5.003
-./usr/lib/perl5/m68k-openbsd/5.003/CORE
-./usr/lib/perl5/m68k-openbsd/5.003/CORE/EXTERN.h
-./usr/lib/perl5/m68k-openbsd/5.003/CORE/INTERN.h
-./usr/lib/perl5/m68k-openbsd/5.003/CORE/XSUB.h
-./usr/lib/perl5/m68k-openbsd/5.003/CORE/av.h
-./usr/lib/perl5/m68k-openbsd/5.003/CORE/config.h
-./usr/lib/perl5/m68k-openbsd/5.003/CORE/cop.h
-./usr/lib/perl5/m68k-openbsd/5.003/CORE/cv.h
-./usr/lib/perl5/m68k-openbsd/5.003/CORE/dosish.h
-./usr/lib/perl5/m68k-openbsd/5.003/CORE/embed.h
-./usr/lib/perl5/m68k-openbsd/5.003/CORE/form.h
-./usr/lib/perl5/m68k-openbsd/5.003/CORE/gv.h
-./usr/lib/perl5/m68k-openbsd/5.003/CORE/handy.h
-./usr/lib/perl5/m68k-openbsd/5.003/CORE/hv.h
-./usr/lib/perl5/m68k-openbsd/5.003/CORE/keywords.h
-./usr/lib/perl5/m68k-openbsd/5.003/CORE/libperl.a
-./usr/lib/perl5/m68k-openbsd/5.003/CORE/mg.h
-./usr/lib/perl5/m68k-openbsd/5.003/CORE/op.h
-./usr/lib/perl5/m68k-openbsd/5.003/CORE/opcode.h
-./usr/lib/perl5/m68k-openbsd/5.003/CORE/patchlevel.h
-./usr/lib/perl5/m68k-openbsd/5.003/CORE/perl.h
-./usr/lib/perl5/m68k-openbsd/5.003/CORE/perly.h
-./usr/lib/perl5/m68k-openbsd/5.003/CORE/pp.h
-./usr/lib/perl5/m68k-openbsd/5.003/CORE/proto.h
-./usr/lib/perl5/m68k-openbsd/5.003/CORE/regcomp.h
-./usr/lib/perl5/m68k-openbsd/5.003/CORE/regexp.h
-./usr/lib/perl5/m68k-openbsd/5.003/CORE/scope.h
-./usr/lib/perl5/m68k-openbsd/5.003/CORE/sv.h
-./usr/lib/perl5/m68k-openbsd/5.003/CORE/unixish.h
-./usr/lib/perl5/m68k-openbsd/5.003/CORE/util.h
-./usr/lib/perl5/m68k-openbsd/5.003/Config.pm
-./usr/lib/perl5/m68k-openbsd/5.003/a.out.ph
-./usr/lib/perl5/m68k-openbsd/5.003/ar.ph
-./usr/lib/perl5/m68k-openbsd/5.003/arpa
-./usr/lib/perl5/m68k-openbsd/5.003/arpa/ftp.ph
-./usr/lib/perl5/m68k-openbsd/5.003/arpa/inet.ph
-./usr/lib/perl5/m68k-openbsd/5.003/arpa/nameser.ph
-./usr/lib/perl5/m68k-openbsd/5.003/arpa/telnet.ph
-./usr/lib/perl5/m68k-openbsd/5.003/arpa/tftp.ph
-./usr/lib/perl5/m68k-openbsd/5.003/assert.ph
-./usr/lib/perl5/m68k-openbsd/5.003/auto
-./usr/lib/perl5/m68k-openbsd/5.003/auto/DB_File
-./usr/lib/perl5/m68k-openbsd/5.003/auto/DB_File/DB_File.bs
-./usr/lib/perl5/m68k-openbsd/5.003/auto/DB_File/DB_File.so
-./usr/lib/perl5/m68k-openbsd/5.003/auto/DynaLoader
-./usr/lib/perl5/m68k-openbsd/5.003/auto/DynaLoader/DynaLoader.a
-./usr/lib/perl5/m68k-openbsd/5.003/auto/DynaLoader/extralibs.ld
-./usr/lib/perl5/m68k-openbsd/5.003/auto/Fcntl
-./usr/lib/perl5/m68k-openbsd/5.003/auto/Fcntl/Fcntl.bs
-./usr/lib/perl5/m68k-openbsd/5.003/auto/Fcntl/Fcntl.so
-./usr/lib/perl5/m68k-openbsd/5.003/auto/FileHandle
-./usr/lib/perl5/m68k-openbsd/5.003/auto/FileHandle/FileHandle.bs
-./usr/lib/perl5/m68k-openbsd/5.003/auto/FileHandle/FileHandle.so
-./usr/lib/perl5/m68k-openbsd/5.003/auto/POSIX
-./usr/lib/perl5/m68k-openbsd/5.003/auto/POSIX/POSIX.bs
-./usr/lib/perl5/m68k-openbsd/5.003/auto/POSIX/POSIX.so
-./usr/lib/perl5/m68k-openbsd/5.003/auto/SDBM_File
-./usr/lib/perl5/m68k-openbsd/5.003/auto/SDBM_File/SDBM_File.bs
-./usr/lib/perl5/m68k-openbsd/5.003/auto/SDBM_File/SDBM_File.so
-./usr/lib/perl5/m68k-openbsd/5.003/auto/Safe
-./usr/lib/perl5/m68k-openbsd/5.003/auto/Safe/Safe.bs
-./usr/lib/perl5/m68k-openbsd/5.003/auto/Safe/Safe.so
-./usr/lib/perl5/m68k-openbsd/5.003/auto/Socket
-./usr/lib/perl5/m68k-openbsd/5.003/auto/Socket/Socket.bs
-./usr/lib/perl5/m68k-openbsd/5.003/auto/Socket/Socket.so
-./usr/lib/perl5/m68k-openbsd/5.003/auto/Text
-./usr/lib/perl5/m68k-openbsd/5.003/auto/Text/ParseWords
-./usr/lib/perl5/m68k-openbsd/5.003/bitstring.ph
-./usr/lib/perl5/m68k-openbsd/5.003/blf.ph
-./usr/lib/perl5/m68k-openbsd/5.003/bm.ph
-./usr/lib/perl5/m68k-openbsd/5.003/com_err.ph
-./usr/lib/perl5/m68k-openbsd/5.003/cpio.ph
-./usr/lib/perl5/m68k-openbsd/5.003/ctype.ph
-./usr/lib/perl5/m68k-openbsd/5.003/curses.ph
-./usr/lib/perl5/m68k-openbsd/5.003/db.ph
-./usr/lib/perl5/m68k-openbsd/5.003/des.ph
-./usr/lib/perl5/m68k-openbsd/5.003/dirent.ph
-./usr/lib/perl5/m68k-openbsd/5.003/disktab.ph
-./usr/lib/perl5/m68k-openbsd/5.003/dlfcn.ph
-./usr/lib/perl5/m68k-openbsd/5.003/elf_abi.ph
-./usr/lib/perl5/m68k-openbsd/5.003/err.ph
-./usr/lib/perl5/m68k-openbsd/5.003/errno.ph
-./usr/lib/perl5/m68k-openbsd/5.003/eti.ph
-./usr/lib/perl5/m68k-openbsd/5.003/fcntl.ph
-./usr/lib/perl5/m68k-openbsd/5.003/float.ph
-./usr/lib/perl5/m68k-openbsd/5.003/fnmatch.ph
-./usr/lib/perl5/m68k-openbsd/5.003/form.ph
-./usr/lib/perl5/m68k-openbsd/5.003/frame.ph
-./usr/lib/perl5/m68k-openbsd/5.003/fstab.ph
-./usr/lib/perl5/m68k-openbsd/5.003/fts.ph
-./usr/lib/perl5/m68k-openbsd/5.003/glob.ph
-./usr/lib/perl5/m68k-openbsd/5.003/gmp.ph
-./usr/lib/perl5/m68k-openbsd/5.003/grp.ph
-./usr/lib/perl5/m68k-openbsd/5.003/histedit.ph
-./usr/lib/perl5/m68k-openbsd/5.003/ieeefp.ph
-./usr/lib/perl5/m68k-openbsd/5.003/inttypes.ph
-./usr/lib/perl5/m68k-openbsd/5.003/iso646.ph
-./usr/lib/perl5/m68k-openbsd/5.003/kvm.ph
-./usr/lib/perl5/m68k-openbsd/5.003/langinfo.ph
-./usr/lib/perl5/m68k-openbsd/5.003/libgen.ph
-./usr/lib/perl5/m68k-openbsd/5.003/limits.ph
-./usr/lib/perl5/m68k-openbsd/5.003/link.ph
-./usr/lib/perl5/m68k-openbsd/5.003/locale.ph
-./usr/lib/perl5/m68k-openbsd/5.003/machine
-./usr/lib/perl5/m68k-openbsd/5.003/machine/ansi.ph
-./usr/lib/perl5/m68k-openbsd/5.003/machine/asm.ph
-./usr/lib/perl5/m68k-openbsd/5.003/machine/autoconf.ph
-./usr/lib/perl5/m68k-openbsd/5.003/machine/cdefs.ph
-./usr/lib/perl5/m68k-openbsd/5.003/machine/cpu.ph
-./usr/lib/perl5/m68k-openbsd/5.003/machine/db_machdep.ph
-./usr/lib/perl5/m68k-openbsd/5.003/machine/disklabel.ph
-./usr/lib/perl5/m68k-openbsd/5.003/machine/endian.ph
-./usr/lib/perl5/m68k-openbsd/5.003/machine/exec.ph
-./usr/lib/perl5/m68k-openbsd/5.003/machine/float.ph
-./usr/lib/perl5/m68k-openbsd/5.003/machine/frame.ph
-./usr/lib/perl5/m68k-openbsd/5.003/machine/hpux_machdep.ph
-./usr/lib/perl5/m68k-openbsd/5.003/machine/ieeefp.ph
-./usr/lib/perl5/m68k-openbsd/5.003/machine/limits.ph
-./usr/lib/perl5/m68k-openbsd/5.003/machine/mioctl.ph
-./usr/lib/perl5/m68k-openbsd/5.003/machine/nvram.ph
-./usr/lib/perl5/m68k-openbsd/5.003/machine/param.ph
-./usr/lib/perl5/m68k-openbsd/5.003/machine/pcb.ph
-./usr/lib/perl5/m68k-openbsd/5.003/machine/pmap.ph
-./usr/lib/perl5/m68k-openbsd/5.003/machine/proc.ph
-./usr/lib/perl5/m68k-openbsd/5.003/machine/profile.ph
-./usr/lib/perl5/m68k-openbsd/5.003/machine/prom.ph
-./usr/lib/perl5/m68k-openbsd/5.003/machine/psl.ph
-./usr/lib/perl5/m68k-openbsd/5.003/machine/pte.ph
-./usr/lib/perl5/m68k-openbsd/5.003/machine/ptrace.ph
-./usr/lib/perl5/m68k-openbsd/5.003/machine/reg.ph
-./usr/lib/perl5/m68k-openbsd/5.003/machine/setjmp.ph
-./usr/lib/perl5/m68k-openbsd/5.003/machine/signal.ph
-./usr/lib/perl5/m68k-openbsd/5.003/machine/stdarg.ph
-./usr/lib/perl5/m68k-openbsd/5.003/machine/trap.ph
-./usr/lib/perl5/m68k-openbsd/5.003/machine/types.ph
-./usr/lib/perl5/m68k-openbsd/5.003/machine/varargs.ph
-./usr/lib/perl5/m68k-openbsd/5.003/machine/vmparam.ph
-./usr/lib/perl5/m68k-openbsd/5.003/malloc.ph
-./usr/lib/perl5/m68k-openbsd/5.003/math.ph
-./usr/lib/perl5/m68k-openbsd/5.003/md4.ph
-./usr/lib/perl5/m68k-openbsd/5.003/md5.ph
-./usr/lib/perl5/m68k-openbsd/5.003/memory.ph
-./usr/lib/perl5/m68k-openbsd/5.003/menu.ph
-./usr/lib/perl5/m68k-openbsd/5.003/mpool.ph
-./usr/lib/perl5/m68k-openbsd/5.003/ndbm.ph
-./usr/lib/perl5/m68k-openbsd/5.003/net
-./usr/lib/perl5/m68k-openbsd/5.003/net/bpf.ph
-./usr/lib/perl5/m68k-openbsd/5.003/net/bpfdesc.ph
-./usr/lib/perl5/m68k-openbsd/5.003/net/encap.ph
-./usr/lib/perl5/m68k-openbsd/5.003/net/if.ph
-./usr/lib/perl5/m68k-openbsd/5.003/net/if_arp.ph
-./usr/lib/perl5/m68k-openbsd/5.003/net/if_atm.ph
-./usr/lib/perl5/m68k-openbsd/5.003/net/if_dl.ph
-./usr/lib/perl5/m68k-openbsd/5.003/net/if_fddi.ph
-./usr/lib/perl5/m68k-openbsd/5.003/net/if_llc.ph
-./usr/lib/perl5/m68k-openbsd/5.003/net/if_ppp.ph
-./usr/lib/perl5/m68k-openbsd/5.003/net/if_pppvar.ph
-./usr/lib/perl5/m68k-openbsd/5.003/net/if_slvar.ph
-./usr/lib/perl5/m68k-openbsd/5.003/net/if_stripvar.ph
-./usr/lib/perl5/m68k-openbsd/5.003/net/if_tun.ph
-./usr/lib/perl5/m68k-openbsd/5.003/net/if_types.ph
-./usr/lib/perl5/m68k-openbsd/5.003/net/netisr.ph
-./usr/lib/perl5/m68k-openbsd/5.003/net/pfkeyv2.ph
-./usr/lib/perl5/m68k-openbsd/5.003/net/ppp-comp.ph
-./usr/lib/perl5/m68k-openbsd/5.003/net/ppp_defs.ph
-./usr/lib/perl5/m68k-openbsd/5.003/net/radix.ph
-./usr/lib/perl5/m68k-openbsd/5.003/net/raw_cb.ph
-./usr/lib/perl5/m68k-openbsd/5.003/net/route.ph
-./usr/lib/perl5/m68k-openbsd/5.003/net/slcompress.ph
-./usr/lib/perl5/m68k-openbsd/5.003/net/slip.ph
-./usr/lib/perl5/m68k-openbsd/5.003/net/zlib.ph
-./usr/lib/perl5/m68k-openbsd/5.003/netdb.ph
-./usr/lib/perl5/m68k-openbsd/5.003/netgroup.ph
-./usr/lib/perl5/m68k-openbsd/5.003/nl_types.ph
-./usr/lib/perl5/m68k-openbsd/5.003/nlist.ph
-./usr/lib/perl5/m68k-openbsd/5.003/ocurses.ph
-./usr/lib/perl5/m68k-openbsd/5.003/olf_abi.ph
-./usr/lib/perl5/m68k-openbsd/5.003/panel.ph
-./usr/lib/perl5/m68k-openbsd/5.003/paths.ph
-./usr/lib/perl5/m68k-openbsd/5.003/pcap-namedb.ph
-./usr/lib/perl5/m68k-openbsd/5.003/pcap.ph
-./usr/lib/perl5/m68k-openbsd/5.003/poll.ph
-./usr/lib/perl5/m68k-openbsd/5.003/protocols
-./usr/lib/perl5/m68k-openbsd/5.003/protocols/dumprestore.ph
-./usr/lib/perl5/m68k-openbsd/5.003/protocols/routed.ph
-./usr/lib/perl5/m68k-openbsd/5.003/protocols/rwhod.ph
-./usr/lib/perl5/m68k-openbsd/5.003/protocols/talkd.ph
-./usr/lib/perl5/m68k-openbsd/5.003/protocols/timed.ph
-./usr/lib/perl5/m68k-openbsd/5.003/pwd.ph
-./usr/lib/perl5/m68k-openbsd/5.003/ranlib.ph
-./usr/lib/perl5/m68k-openbsd/5.003/re_comp.ph
-./usr/lib/perl5/m68k-openbsd/5.003/regex.ph
-./usr/lib/perl5/m68k-openbsd/5.003/regexp.ph
-./usr/lib/perl5/m68k-openbsd/5.003/resolv.ph
-./usr/lib/perl5/m68k-openbsd/5.003/rmd160.ph
-./usr/lib/perl5/m68k-openbsd/5.003/scsi.ph
-./usr/lib/perl5/m68k-openbsd/5.003/search.ph
-./usr/lib/perl5/m68k-openbsd/5.003/setjmp.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sgtty.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sha1.ph
-./usr/lib/perl5/m68k-openbsd/5.003/signal.ph
-./usr/lib/perl5/m68k-openbsd/5.003/skey.ph
-./usr/lib/perl5/m68k-openbsd/5.003/stab.ph
-./usr/lib/perl5/m68k-openbsd/5.003/stdarg.ph
-./usr/lib/perl5/m68k-openbsd/5.003/stddef.ph
-./usr/lib/perl5/m68k-openbsd/5.003/stdio.ph
-./usr/lib/perl5/m68k-openbsd/5.003/stdlib.ph
-./usr/lib/perl5/m68k-openbsd/5.003/string.ph
-./usr/lib/perl5/m68k-openbsd/5.003/strings.ph
-./usr/lib/perl5/m68k-openbsd/5.003/struct.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys
-./usr/lib/perl5/m68k-openbsd/5.003/sys/acct.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/audioio.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/buf.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/callout.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/cdefs.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/cdio.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/chio.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/clist.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/conf.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/core.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/device.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/dir.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/dirent.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/disk.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/disklabel.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/dkbad.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/dkio.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/dkstat.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/dmap.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/domain.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/endian.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/errno.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/exec.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/exec_aout.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/exec_ecoff.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/exec_elf.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/exec_olf.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/exec_script.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/extent.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/fcntl.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/file.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/filedesc.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/filio.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/gmon.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/ioccom.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/ioctl.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/ioctl_compat.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/ipc.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/kcore.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/kernel.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/ktrace.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/lkm.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/localedef.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/lock.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/lockf.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/malloc.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/map.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/mbuf.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/md5k.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/mman.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/mount.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/msg.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/msgbuf.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/mtio.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/namei.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/param.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/pipe.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/poll.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/proc.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/protosw.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/ptrace.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/queue.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/reboot.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/resource.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/resourcevar.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/scanio.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/scsiio.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/select.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/sem.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/shm.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/siginfo.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/signal.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/signalvar.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/simplelock.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/socket.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/socketvar.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/sockio.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/stat.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/syscall.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/syscallargs.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/sysctl.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/syslimits.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/syslog.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/systm.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/tablet.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/termios.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/time.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/timeb.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/times.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/timex.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/tprintf.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/trace.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/tty.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/ttychars.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/ttycom.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/ttydefaults.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/ttydev.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/types.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/ucred.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/uio.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/un.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/unistd.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/unpcb.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/user.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/utsname.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/vadvise.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/vcmd.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/vlimit.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/vmmeter.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/vnode.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/vnode_if.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/vsio.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sys/wait.ph
-./usr/lib/perl5/m68k-openbsd/5.003/sysexits.ph
-./usr/lib/perl5/m68k-openbsd/5.003/syslog.ph
-./usr/lib/perl5/m68k-openbsd/5.003/tar.ph
-./usr/lib/perl5/m68k-openbsd/5.003/tcpd.ph
-./usr/lib/perl5/m68k-openbsd/5.003/term.ph
-./usr/lib/perl5/m68k-openbsd/5.003/termios.ph
-./usr/lib/perl5/m68k-openbsd/5.003/time.ph
-./usr/lib/perl5/m68k-openbsd/5.003/ttyent.ph
-./usr/lib/perl5/m68k-openbsd/5.003/tzfile.ph
-./usr/lib/perl5/m68k-openbsd/5.003/unctrl.ph
-./usr/lib/perl5/m68k-openbsd/5.003/unistd.ph
-./usr/lib/perl5/m68k-openbsd/5.003/util.ph
-./usr/lib/perl5/m68k-openbsd/5.003/utime.ph
-./usr/lib/perl5/m68k-openbsd/5.003/utmp.ph
-./usr/lib/perl5/m68k-openbsd/5.003/varargs.ph
-./usr/lib/perl5/m68k-openbsd/5.003/vis.ph
-./usr/lib/perl5/m68k-openbsd/5.003/zconf.ph
-./usr/lib/perl5/m68k-openbsd/5.003/zlib.ph
./usr/lib/perl5/site_perl/m68k-openbsd
./usr/libexec/ld.so
./usr/mdec/bootsd
diff --git a/distrib/sets/lists/base/md.sparc b/distrib/sets/lists/base/md.sparc
index 91b57f516c3..0b28b4c68d8 100644
--- a/distrib/sets/lists/base/md.sparc
+++ b/distrib/sets/lists/base/md.sparc
@@ -35,541 +35,6 @@
./usr/lib/libutil.so.4.1
./usr/lib/libwrap.so.1.0
./usr/lib/libz.so.1.2
-./usr/lib/perl5/DB_File.pm
-./usr/lib/perl5/Fcntl.pm
-./usr/lib/perl5/FileHandle.pm
-./usr/lib/perl5/POSIX.pm
-./usr/lib/perl5/POSIX.pod
-./usr/lib/perl5/SDBM_File.pm
-./usr/lib/perl5/Safe.pm
-./usr/lib/perl5/Socket.pm
-./usr/lib/perl5/auto/DB_File
-./usr/lib/perl5/auto/DB_File/autosplit.ix
-./usr/lib/perl5/auto/Fcntl
-./usr/lib/perl5/auto/Fcntl/autosplit.ix
-./usr/lib/perl5/auto/POSIX
-./usr/lib/perl5/auto/POSIX/abs.al
-./usr/lib/perl5/auto/POSIX/alarm.al
-./usr/lib/perl5/auto/POSIX/assert.al
-./usr/lib/perl5/auto/POSIX/atan2.al
-./usr/lib/perl5/auto/POSIX/atexit.al
-./usr/lib/perl5/auto/POSIX/atof.al
-./usr/lib/perl5/auto/POSIX/atoi.al
-./usr/lib/perl5/auto/POSIX/atol.al
-./usr/lib/perl5/auto/POSIX/autosplit.ix
-./usr/lib/perl5/auto/POSIX/bsearch.al
-./usr/lib/perl5/auto/POSIX/calloc.al
-./usr/lib/perl5/auto/POSIX/chdir.al
-./usr/lib/perl5/auto/POSIX/chmod.al
-./usr/lib/perl5/auto/POSIX/chown.al
-./usr/lib/perl5/auto/POSIX/clearerr.al
-./usr/lib/perl5/auto/POSIX/closedir.al
-./usr/lib/perl5/auto/POSIX/cos.al
-./usr/lib/perl5/auto/POSIX/creat.al
-./usr/lib/perl5/auto/POSIX/div.al
-./usr/lib/perl5/auto/POSIX/errno.al
-./usr/lib/perl5/auto/POSIX/execl.al
-./usr/lib/perl5/auto/POSIX/execle.al
-./usr/lib/perl5/auto/POSIX/execlp.al
-./usr/lib/perl5/auto/POSIX/execv.al
-./usr/lib/perl5/auto/POSIX/execve.al
-./usr/lib/perl5/auto/POSIX/execvp.al
-./usr/lib/perl5/auto/POSIX/exit.al
-./usr/lib/perl5/auto/POSIX/exp.al
-./usr/lib/perl5/auto/POSIX/fabs.al
-./usr/lib/perl5/auto/POSIX/fclose.al
-./usr/lib/perl5/auto/POSIX/fcntl.al
-./usr/lib/perl5/auto/POSIX/fdopen.al
-./usr/lib/perl5/auto/POSIX/feof.al
-./usr/lib/perl5/auto/POSIX/ferror.al
-./usr/lib/perl5/auto/POSIX/fflush.al
-./usr/lib/perl5/auto/POSIX/fgetc.al
-./usr/lib/perl5/auto/POSIX/fgetpos.al
-./usr/lib/perl5/auto/POSIX/fgets.al
-./usr/lib/perl5/auto/POSIX/fileno.al
-./usr/lib/perl5/auto/POSIX/fopen.al
-./usr/lib/perl5/auto/POSIX/fork.al
-./usr/lib/perl5/auto/POSIX/fprintf.al
-./usr/lib/perl5/auto/POSIX/fputc.al
-./usr/lib/perl5/auto/POSIX/fputs.al
-./usr/lib/perl5/auto/POSIX/fread.al
-./usr/lib/perl5/auto/POSIX/free.al
-./usr/lib/perl5/auto/POSIX/freopen.al
-./usr/lib/perl5/auto/POSIX/fscanf.al
-./usr/lib/perl5/auto/POSIX/fseek.al
-./usr/lib/perl5/auto/POSIX/fsetpos.al
-./usr/lib/perl5/auto/POSIX/fstat.al
-./usr/lib/perl5/auto/POSIX/ftell.al
-./usr/lib/perl5/auto/POSIX/fwrite.al
-./usr/lib/perl5/auto/POSIX/getc.al
-./usr/lib/perl5/auto/POSIX/getchar.al
-./usr/lib/perl5/auto/POSIX/getcwd.al
-./usr/lib/perl5/auto/POSIX/getegid.al
-./usr/lib/perl5/auto/POSIX/getenv.al
-./usr/lib/perl5/auto/POSIX/geteuid.al
-./usr/lib/perl5/auto/POSIX/getgid.al
-./usr/lib/perl5/auto/POSIX/getgrgid.al
-./usr/lib/perl5/auto/POSIX/getgrnam.al
-./usr/lib/perl5/auto/POSIX/getgroups.al
-./usr/lib/perl5/auto/POSIX/getlogin.al
-./usr/lib/perl5/auto/POSIX/getpgrp.al
-./usr/lib/perl5/auto/POSIX/getpid.al
-./usr/lib/perl5/auto/POSIX/getppid.al
-./usr/lib/perl5/auto/POSIX/getpwnam.al
-./usr/lib/perl5/auto/POSIX/getpwuid.al
-./usr/lib/perl5/auto/POSIX/gets.al
-./usr/lib/perl5/auto/POSIX/getuid.al
-./usr/lib/perl5/auto/POSIX/gmtime.al
-./usr/lib/perl5/auto/POSIX/isatty.al
-./usr/lib/perl5/auto/POSIX/kill.al
-./usr/lib/perl5/auto/POSIX/labs.al
-./usr/lib/perl5/auto/POSIX/ldiv.al
-./usr/lib/perl5/auto/POSIX/link.al
-./usr/lib/perl5/auto/POSIX/localtime.al
-./usr/lib/perl5/auto/POSIX/log.al
-./usr/lib/perl5/auto/POSIX/longjmp.al
-./usr/lib/perl5/auto/POSIX/malloc.al
-./usr/lib/perl5/auto/POSIX/memchr.al
-./usr/lib/perl5/auto/POSIX/memcmp.al
-./usr/lib/perl5/auto/POSIX/memcpy.al
-./usr/lib/perl5/auto/POSIX/memmove.al
-./usr/lib/perl5/auto/POSIX/memset.al
-./usr/lib/perl5/auto/POSIX/mkdir.al
-./usr/lib/perl5/auto/POSIX/offsetof.al
-./usr/lib/perl5/auto/POSIX/opendir.al
-./usr/lib/perl5/auto/POSIX/perror.al
-./usr/lib/perl5/auto/POSIX/pow.al
-./usr/lib/perl5/auto/POSIX/printf.al
-./usr/lib/perl5/auto/POSIX/putc.al
-./usr/lib/perl5/auto/POSIX/putchar.al
-./usr/lib/perl5/auto/POSIX/puts.al
-./usr/lib/perl5/auto/POSIX/qsort.al
-./usr/lib/perl5/auto/POSIX/raise.al
-./usr/lib/perl5/auto/POSIX/rand.al
-./usr/lib/perl5/auto/POSIX/readdir.al
-./usr/lib/perl5/auto/POSIX/realloc.al
-./usr/lib/perl5/auto/POSIX/remove.al
-./usr/lib/perl5/auto/POSIX/rename.al
-./usr/lib/perl5/auto/POSIX/rewind.al
-./usr/lib/perl5/auto/POSIX/rewinddir.al
-./usr/lib/perl5/auto/POSIX/rmdir.al
-./usr/lib/perl5/auto/POSIX/scanf.al
-./usr/lib/perl5/auto/POSIX/setgid.al
-./usr/lib/perl5/auto/POSIX/setjmp.al
-./usr/lib/perl5/auto/POSIX/setuid.al
-./usr/lib/perl5/auto/POSIX/siglongjmp.al
-./usr/lib/perl5/auto/POSIX/sigsetjmp.al
-./usr/lib/perl5/auto/POSIX/sin.al
-./usr/lib/perl5/auto/POSIX/sleep.al
-./usr/lib/perl5/auto/POSIX/sprintf.al
-./usr/lib/perl5/auto/POSIX/sqrt.al
-./usr/lib/perl5/auto/POSIX/srand.al
-./usr/lib/perl5/auto/POSIX/sscanf.al
-./usr/lib/perl5/auto/POSIX/stat.al
-./usr/lib/perl5/auto/POSIX/strcat.al
-./usr/lib/perl5/auto/POSIX/strchr.al
-./usr/lib/perl5/auto/POSIX/strcmp.al
-./usr/lib/perl5/auto/POSIX/strcpy.al
-./usr/lib/perl5/auto/POSIX/strcspn.al
-./usr/lib/perl5/auto/POSIX/strerror.al
-./usr/lib/perl5/auto/POSIX/strlen.al
-./usr/lib/perl5/auto/POSIX/strncat.al
-./usr/lib/perl5/auto/POSIX/strncmp.al
-./usr/lib/perl5/auto/POSIX/strncpy.al
-./usr/lib/perl5/auto/POSIX/stroul.al
-./usr/lib/perl5/auto/POSIX/strpbrk.al
-./usr/lib/perl5/auto/POSIX/strrchr.al
-./usr/lib/perl5/auto/POSIX/strspn.al
-./usr/lib/perl5/auto/POSIX/strstr.al
-./usr/lib/perl5/auto/POSIX/strtod.al
-./usr/lib/perl5/auto/POSIX/strtok.al
-./usr/lib/perl5/auto/POSIX/strtol.al
-./usr/lib/perl5/auto/POSIX/system.al
-./usr/lib/perl5/auto/POSIX/time.al
-./usr/lib/perl5/auto/POSIX/tmpfile.al
-./usr/lib/perl5/auto/POSIX/tolower.al
-./usr/lib/perl5/auto/POSIX/toupper.al
-./usr/lib/perl5/auto/POSIX/umask.al
-./usr/lib/perl5/auto/POSIX/ungetc.al
-./usr/lib/perl5/auto/POSIX/unlink.al
-./usr/lib/perl5/auto/POSIX/utime.al
-./usr/lib/perl5/auto/POSIX/vfprintf.al
-./usr/lib/perl5/auto/POSIX/vprintf.al
-./usr/lib/perl5/auto/POSIX/vsprintf.al
-./usr/lib/perl5/auto/POSIX/wait.al
-./usr/lib/perl5/auto/POSIX/waitpid.al
-./usr/lib/perl5/auto/Socket
-./usr/lib/perl5/auto/Socket/autosplit.ix
-./usr/lib/perl5/auto/Text
-./usr/lib/perl5/auto/Text/ParseWords
-./usr/lib/perl5/auto/Text/ParseWords/autosplit.ix
-./usr/lib/perl5/auto/Text/ParseWords/old_shellwords.al
-./usr/lib/perl5/auto/Text/ParseWords/quotewords.al
-./usr/lib/perl5/auto/Text/ParseWords/shellwords.al
-./usr/lib/perl5/site_perl/sparc-openbsd
-./usr/lib/perl5/sparc-openbsd
-./usr/lib/perl5/sparc-openbsd/5.003
-./usr/lib/perl5/sparc-openbsd/5.003/CORE
-./usr/lib/perl5/sparc-openbsd/5.003/CORE/EXTERN.h
-./usr/lib/perl5/sparc-openbsd/5.003/CORE/INTERN.h
-./usr/lib/perl5/sparc-openbsd/5.003/CORE/XSUB.h
-./usr/lib/perl5/sparc-openbsd/5.003/CORE/av.h
-./usr/lib/perl5/sparc-openbsd/5.003/CORE/config.h
-./usr/lib/perl5/sparc-openbsd/5.003/CORE/cop.h
-./usr/lib/perl5/sparc-openbsd/5.003/CORE/cv.h
-./usr/lib/perl5/sparc-openbsd/5.003/CORE/dosish.h
-./usr/lib/perl5/sparc-openbsd/5.003/CORE/embed.h
-./usr/lib/perl5/sparc-openbsd/5.003/CORE/form.h
-./usr/lib/perl5/sparc-openbsd/5.003/CORE/gv.h
-./usr/lib/perl5/sparc-openbsd/5.003/CORE/handy.h
-./usr/lib/perl5/sparc-openbsd/5.003/CORE/hv.h
-./usr/lib/perl5/sparc-openbsd/5.003/CORE/keywords.h
-./usr/lib/perl5/sparc-openbsd/5.003/CORE/libperl.a
-./usr/lib/perl5/sparc-openbsd/5.003/CORE/mg.h
-./usr/lib/perl5/sparc-openbsd/5.003/CORE/op.h
-./usr/lib/perl5/sparc-openbsd/5.003/CORE/opcode.h
-./usr/lib/perl5/sparc-openbsd/5.003/CORE/patchlevel.h
-./usr/lib/perl5/sparc-openbsd/5.003/CORE/perl.h
-./usr/lib/perl5/sparc-openbsd/5.003/CORE/perly.h
-./usr/lib/perl5/sparc-openbsd/5.003/CORE/pp.h
-./usr/lib/perl5/sparc-openbsd/5.003/CORE/proto.h
-./usr/lib/perl5/sparc-openbsd/5.003/CORE/regcomp.h
-./usr/lib/perl5/sparc-openbsd/5.003/CORE/regexp.h
-./usr/lib/perl5/sparc-openbsd/5.003/CORE/scope.h
-./usr/lib/perl5/sparc-openbsd/5.003/CORE/sv.h
-./usr/lib/perl5/sparc-openbsd/5.003/CORE/unixish.h
-./usr/lib/perl5/sparc-openbsd/5.003/CORE/util.h
-./usr/lib/perl5/sparc-openbsd/5.003/Config.pm
-./usr/lib/perl5/sparc-openbsd/5.003/a.out.ph
-./usr/lib/perl5/sparc-openbsd/5.003/ar.ph
-./usr/lib/perl5/sparc-openbsd/5.003/arpa
-./usr/lib/perl5/sparc-openbsd/5.003/arpa/ftp.ph
-./usr/lib/perl5/sparc-openbsd/5.003/arpa/inet.ph
-./usr/lib/perl5/sparc-openbsd/5.003/arpa/nameser.ph
-./usr/lib/perl5/sparc-openbsd/5.003/arpa/telnet.ph
-./usr/lib/perl5/sparc-openbsd/5.003/arpa/tftp.ph
-./usr/lib/perl5/sparc-openbsd/5.003/assert.ph
-./usr/lib/perl5/sparc-openbsd/5.003/auto
-./usr/lib/perl5/sparc-openbsd/5.003/auto/DB_File
-./usr/lib/perl5/sparc-openbsd/5.003/auto/DB_File/DB_File.bs
-./usr/lib/perl5/sparc-openbsd/5.003/auto/DB_File/DB_File.so
-./usr/lib/perl5/sparc-openbsd/5.003/auto/DynaLoader
-./usr/lib/perl5/sparc-openbsd/5.003/auto/DynaLoader/DynaLoader.a
-./usr/lib/perl5/sparc-openbsd/5.003/auto/DynaLoader/extralibs.ld
-./usr/lib/perl5/sparc-openbsd/5.003/auto/Fcntl
-./usr/lib/perl5/sparc-openbsd/5.003/auto/Fcntl/Fcntl.bs
-./usr/lib/perl5/sparc-openbsd/5.003/auto/Fcntl/Fcntl.so
-./usr/lib/perl5/sparc-openbsd/5.003/auto/FileHandle
-./usr/lib/perl5/sparc-openbsd/5.003/auto/FileHandle/FileHandle.bs
-./usr/lib/perl5/sparc-openbsd/5.003/auto/FileHandle/FileHandle.so
-./usr/lib/perl5/sparc-openbsd/5.003/auto/POSIX
-./usr/lib/perl5/sparc-openbsd/5.003/auto/POSIX/POSIX.bs
-./usr/lib/perl5/sparc-openbsd/5.003/auto/POSIX/POSIX.so
-./usr/lib/perl5/sparc-openbsd/5.003/auto/SDBM_File
-./usr/lib/perl5/sparc-openbsd/5.003/auto/SDBM_File/SDBM_File.bs
-./usr/lib/perl5/sparc-openbsd/5.003/auto/SDBM_File/SDBM_File.so
-./usr/lib/perl5/sparc-openbsd/5.003/auto/Safe
-./usr/lib/perl5/sparc-openbsd/5.003/auto/Safe/Safe.bs
-./usr/lib/perl5/sparc-openbsd/5.003/auto/Safe/Safe.so
-./usr/lib/perl5/sparc-openbsd/5.003/auto/Socket
-./usr/lib/perl5/sparc-openbsd/5.003/auto/Socket/Socket.bs
-./usr/lib/perl5/sparc-openbsd/5.003/auto/Socket/Socket.so
-./usr/lib/perl5/sparc-openbsd/5.003/auto/Text
-./usr/lib/perl5/sparc-openbsd/5.003/auto/Text/ParseWords
-./usr/lib/perl5/sparc-openbsd/5.003/bitstring.ph
-./usr/lib/perl5/sparc-openbsd/5.003/blf.ph
-./usr/lib/perl5/sparc-openbsd/5.003/bm.ph
-./usr/lib/perl5/sparc-openbsd/5.003/com_err.ph
-./usr/lib/perl5/sparc-openbsd/5.003/cpio.ph
-./usr/lib/perl5/sparc-openbsd/5.003/ctype.ph
-./usr/lib/perl5/sparc-openbsd/5.003/curses.ph
-./usr/lib/perl5/sparc-openbsd/5.003/db.ph
-./usr/lib/perl5/sparc-openbsd/5.003/des.ph
-./usr/lib/perl5/sparc-openbsd/5.003/dirent.ph
-./usr/lib/perl5/sparc-openbsd/5.003/disktab.ph
-./usr/lib/perl5/sparc-openbsd/5.003/dlfcn.ph
-./usr/lib/perl5/sparc-openbsd/5.003/elf_abi.ph
-./usr/lib/perl5/sparc-openbsd/5.003/err.ph
-./usr/lib/perl5/sparc-openbsd/5.003/errno.ph
-./usr/lib/perl5/sparc-openbsd/5.003/eti.ph
-./usr/lib/perl5/sparc-openbsd/5.003/fcntl.ph
-./usr/lib/perl5/sparc-openbsd/5.003/float.ph
-./usr/lib/perl5/sparc-openbsd/5.003/fnmatch.ph
-./usr/lib/perl5/sparc-openbsd/5.003/form.ph
-./usr/lib/perl5/sparc-openbsd/5.003/frame.ph
-./usr/lib/perl5/sparc-openbsd/5.003/fstab.ph
-./usr/lib/perl5/sparc-openbsd/5.003/fts.ph
-./usr/lib/perl5/sparc-openbsd/5.003/glob.ph
-./usr/lib/perl5/sparc-openbsd/5.003/gmp.ph
-./usr/lib/perl5/sparc-openbsd/5.003/grp.ph
-./usr/lib/perl5/sparc-openbsd/5.003/histedit.ph
-./usr/lib/perl5/sparc-openbsd/5.003/ieeefp.ph
-./usr/lib/perl5/sparc-openbsd/5.003/inttypes.ph
-./usr/lib/perl5/sparc-openbsd/5.003/iso646.ph
-./usr/lib/perl5/sparc-openbsd/5.003/kvm.ph
-./usr/lib/perl5/sparc-openbsd/5.003/langinfo.ph
-./usr/lib/perl5/sparc-openbsd/5.003/libgen.ph
-./usr/lib/perl5/sparc-openbsd/5.003/limits.ph
-./usr/lib/perl5/sparc-openbsd/5.003/link.ph
-./usr/lib/perl5/sparc-openbsd/5.003/locale.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine
-./usr/lib/perl5/sparc-openbsd/5.003/machine/ansi.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/asm.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/autoconf.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/bsd_audioio.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/bsd_openprom.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/cdefs.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/cgtworeg.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/conf.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/cpu.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/ctlreg.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/db_machdep.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/disklabel.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/eeprom.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/endian.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/exec.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/fbio.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/fbvar.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/float.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/frame.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/fsr.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/idprom.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/ieee.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/ieeefp.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/instr.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/ioctl_fd.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/kbd.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/kbio.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/kcore.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/limits.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/oldmon.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/openpromio.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/param.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/pcb.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/pmap.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/proc.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/profile.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/psl.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/pte.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/ptrace.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/reg.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/reloc.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/remote-sl.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/setjmp.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/signal.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/stdarg.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/sun_disklabel.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/svr4_machdep.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/trap.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/types.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/varargs.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/vmparam.ph
-./usr/lib/perl5/sparc-openbsd/5.003/machine/vuid_event.ph
-./usr/lib/perl5/sparc-openbsd/5.003/malloc.ph
-./usr/lib/perl5/sparc-openbsd/5.003/math.ph
-./usr/lib/perl5/sparc-openbsd/5.003/md4.ph
-./usr/lib/perl5/sparc-openbsd/5.003/md5.ph
-./usr/lib/perl5/sparc-openbsd/5.003/memory.ph
-./usr/lib/perl5/sparc-openbsd/5.003/menu.ph
-./usr/lib/perl5/sparc-openbsd/5.003/mpool.ph
-./usr/lib/perl5/sparc-openbsd/5.003/ndbm.ph
-./usr/lib/perl5/sparc-openbsd/5.003/net
-./usr/lib/perl5/sparc-openbsd/5.003/net/bpf.ph
-./usr/lib/perl5/sparc-openbsd/5.003/net/bpfdesc.ph
-./usr/lib/perl5/sparc-openbsd/5.003/net/encap.ph
-./usr/lib/perl5/sparc-openbsd/5.003/net/if.ph
-./usr/lib/perl5/sparc-openbsd/5.003/net/if_arp.ph
-./usr/lib/perl5/sparc-openbsd/5.003/net/if_atm.ph
-./usr/lib/perl5/sparc-openbsd/5.003/net/if_dl.ph
-./usr/lib/perl5/sparc-openbsd/5.003/net/if_fddi.ph
-./usr/lib/perl5/sparc-openbsd/5.003/net/if_llc.ph
-./usr/lib/perl5/sparc-openbsd/5.003/net/if_ppp.ph
-./usr/lib/perl5/sparc-openbsd/5.003/net/if_pppvar.ph
-./usr/lib/perl5/sparc-openbsd/5.003/net/if_slvar.ph
-./usr/lib/perl5/sparc-openbsd/5.003/net/if_stripvar.ph
-./usr/lib/perl5/sparc-openbsd/5.003/net/if_tun.ph
-./usr/lib/perl5/sparc-openbsd/5.003/net/if_types.ph
-./usr/lib/perl5/sparc-openbsd/5.003/net/netisr.ph
-./usr/lib/perl5/sparc-openbsd/5.003/net/pfkeyv2.ph
-./usr/lib/perl5/sparc-openbsd/5.003/net/ppp-comp.ph
-./usr/lib/perl5/sparc-openbsd/5.003/net/ppp_defs.ph
-./usr/lib/perl5/sparc-openbsd/5.003/net/radix.ph
-./usr/lib/perl5/sparc-openbsd/5.003/net/raw_cb.ph
-./usr/lib/perl5/sparc-openbsd/5.003/net/route.ph
-./usr/lib/perl5/sparc-openbsd/5.003/net/slcompress.ph
-./usr/lib/perl5/sparc-openbsd/5.003/net/slip.ph
-./usr/lib/perl5/sparc-openbsd/5.003/net/zlib.ph
-./usr/lib/perl5/sparc-openbsd/5.003/netdb.ph
-./usr/lib/perl5/sparc-openbsd/5.003/netgroup.ph
-./usr/lib/perl5/sparc-openbsd/5.003/nl_types.ph
-./usr/lib/perl5/sparc-openbsd/5.003/nlist.ph
-./usr/lib/perl5/sparc-openbsd/5.003/ocurses.ph
-./usr/lib/perl5/sparc-openbsd/5.003/olf_abi.ph
-./usr/lib/perl5/sparc-openbsd/5.003/panel.ph
-./usr/lib/perl5/sparc-openbsd/5.003/paths.ph
-./usr/lib/perl5/sparc-openbsd/5.003/pcap-namedb.ph
-./usr/lib/perl5/sparc-openbsd/5.003/pcap.ph
-./usr/lib/perl5/sparc-openbsd/5.003/poll.ph
-./usr/lib/perl5/sparc-openbsd/5.003/protocols
-./usr/lib/perl5/sparc-openbsd/5.003/protocols/dumprestore.ph
-./usr/lib/perl5/sparc-openbsd/5.003/protocols/routed.ph
-./usr/lib/perl5/sparc-openbsd/5.003/protocols/rwhod.ph
-./usr/lib/perl5/sparc-openbsd/5.003/protocols/talkd.ph
-./usr/lib/perl5/sparc-openbsd/5.003/protocols/timed.ph
-./usr/lib/perl5/sparc-openbsd/5.003/pwd.ph
-./usr/lib/perl5/sparc-openbsd/5.003/ranlib.ph
-./usr/lib/perl5/sparc-openbsd/5.003/re_comp.ph
-./usr/lib/perl5/sparc-openbsd/5.003/regex.ph
-./usr/lib/perl5/sparc-openbsd/5.003/regexp.ph
-./usr/lib/perl5/sparc-openbsd/5.003/resolv.ph
-./usr/lib/perl5/sparc-openbsd/5.003/rmd160.ph
-./usr/lib/perl5/sparc-openbsd/5.003/scsi.ph
-./usr/lib/perl5/sparc-openbsd/5.003/search.ph
-./usr/lib/perl5/sparc-openbsd/5.003/setjmp.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sgtty.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sha1.ph
-./usr/lib/perl5/sparc-openbsd/5.003/signal.ph
-./usr/lib/perl5/sparc-openbsd/5.003/skey.ph
-./usr/lib/perl5/sparc-openbsd/5.003/stab.ph
-./usr/lib/perl5/sparc-openbsd/5.003/stdarg.ph
-./usr/lib/perl5/sparc-openbsd/5.003/stddef.ph
-./usr/lib/perl5/sparc-openbsd/5.003/stdio.ph
-./usr/lib/perl5/sparc-openbsd/5.003/stdlib.ph
-./usr/lib/perl5/sparc-openbsd/5.003/string.ph
-./usr/lib/perl5/sparc-openbsd/5.003/strings.ph
-./usr/lib/perl5/sparc-openbsd/5.003/struct.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys
-./usr/lib/perl5/sparc-openbsd/5.003/sys/acct.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/audioio.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/buf.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/callout.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/cdefs.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/cdio.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/chio.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/clist.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/conf.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/core.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/device.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/dir.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/dirent.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/disk.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/disklabel.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/dkbad.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/dkio.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/dkstat.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/dmap.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/domain.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/endian.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/errno.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/exec.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/exec_aout.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/exec_ecoff.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/exec_elf.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/exec_olf.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/exec_script.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/extent.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/fcntl.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/file.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/filedesc.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/filio.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/gmon.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/ioccom.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/ioctl.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/ioctl_compat.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/ipc.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/kcore.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/kernel.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/ktrace.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/lkm.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/localedef.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/lock.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/lockf.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/malloc.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/map.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/mbuf.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/md5k.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/mman.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/mount.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/msg.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/msgbuf.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/mtio.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/namei.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/param.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/pipe.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/poll.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/proc.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/protosw.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/ptrace.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/queue.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/reboot.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/resource.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/resourcevar.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/scanio.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/scsiio.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/select.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/sem.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/shm.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/siginfo.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/signal.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/signalvar.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/simplelock.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/socket.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/socketvar.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/sockio.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/stat.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/syscall.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/syscallargs.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/sysctl.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/syslimits.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/syslog.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/systm.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/tablet.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/termios.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/time.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/timeb.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/times.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/timex.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/tprintf.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/trace.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/tty.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/ttychars.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/ttycom.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/ttydefaults.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/ttydev.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/types.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/ucred.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/uio.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/un.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/unistd.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/unpcb.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/user.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/utsname.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/vadvise.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/vcmd.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/vlimit.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/vmmeter.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/vnode.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/vnode_if.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/vsio.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sys/wait.ph
-./usr/lib/perl5/sparc-openbsd/5.003/sysexits.ph
-./usr/lib/perl5/sparc-openbsd/5.003/syslog.ph
-./usr/lib/perl5/sparc-openbsd/5.003/tar.ph
-./usr/lib/perl5/sparc-openbsd/5.003/tcpd.ph
-./usr/lib/perl5/sparc-openbsd/5.003/term.ph
-./usr/lib/perl5/sparc-openbsd/5.003/termios.ph
-./usr/lib/perl5/sparc-openbsd/5.003/time.ph
-./usr/lib/perl5/sparc-openbsd/5.003/ttyent.ph
-./usr/lib/perl5/sparc-openbsd/5.003/tzfile.ph
-./usr/lib/perl5/sparc-openbsd/5.003/unctrl.ph
-./usr/lib/perl5/sparc-openbsd/5.003/unistd.ph
-./usr/lib/perl5/sparc-openbsd/5.003/util.ph
-./usr/lib/perl5/sparc-openbsd/5.003/utime.ph
-./usr/lib/perl5/sparc-openbsd/5.003/utmp.ph
-./usr/lib/perl5/sparc-openbsd/5.003/varargs.ph
-./usr/lib/perl5/sparc-openbsd/5.003/vis.ph
-./usr/lib/perl5/sparc-openbsd/5.003/zconf.ph
-./usr/lib/perl5/sparc-openbsd/5.003/zlib.ph
./usr/libexec/ld.so
./usr/mdec/binstall
./usr/mdec/boot
diff --git a/distrib/sets/lists/base/mi b/distrib/sets/lists/base/mi
index 1cce25a7edf..ed478308668 100644
--- a/distrib/sets/lists/base/mi
+++ b/distrib/sets/lists/base/mi
@@ -1,3 +1,4 @@
+./usr/lib/perl5/Pod/Html.pm
.
./altroot
./bin
@@ -287,9 +288,10 @@
./usr/bin/paste
./usr/bin/patch
./usr/bin/perl
-./usr/bin/perl5.003
+./usr/bin/perl5.00404
./usr/bin/perlbug
./usr/bin/perldoc
+./usr/bin/pl2pm
./usr/bin/pr
./usr/bin/printenv
./usr/bin/printf
@@ -334,6 +336,7 @@
./usr/bin/skeyinit
./usr/bin/skeyprune
./usr/bin/sort
+./usr/bin/splain
./usr/bin/split
./usr/bin/strings
./usr/bin/su
@@ -459,21 +462,38 @@
./usr/lib/perl5/AutoLoader.pm
./usr/lib/perl5/AutoSplit.pm
./usr/lib/perl5/Benchmark.pm
+./usr/lib/perl5/Bundle
+./usr/lib/perl5/Bundle/CPAN.pm
+./usr/lib/perl5/CGI
+./usr/lib/perl5/CGI.pm
+./usr/lib/perl5/CGI/Apache.pm
+./usr/lib/perl5/CGI/Carp.pm
+./usr/lib/perl5/CGI/Fast.pm
+./usr/lib/perl5/CGI/Push.pm
+./usr/lib/perl5/CGI/Switch.pm
+./usr/lib/perl5/CPAN
+./usr/lib/perl5/CPAN.pm
+./usr/lib/perl5/CPAN/FirstTime.pm
+./usr/lib/perl5/CPAN/Nox.pm
./usr/lib/perl5/Carp.pm
+./usr/lib/perl5/Class
+./usr/lib/perl5/Class/Struct.pm
./usr/lib/perl5/Cwd.pm
./usr/lib/perl5/Devel
./usr/lib/perl5/Devel/SelfStubber.pm
./usr/lib/perl5/DirHandle.pm
-./usr/lib/perl5/DynaLoader.pm
./usr/lib/perl5/English.pm
./usr/lib/perl5/Env.pm
./usr/lib/perl5/Exporter.pm
./usr/lib/perl5/ExtUtils
+./usr/lib/perl5/ExtUtils/Command.pm
+./usr/lib/perl5/ExtUtils/Embed.pm
./usr/lib/perl5/ExtUtils/Install.pm
./usr/lib/perl5/ExtUtils/Liblist.pm
./usr/lib/perl5/ExtUtils/MM_OS2.pm
./usr/lib/perl5/ExtUtils/MM_Unix.pm
./usr/lib/perl5/ExtUtils/MM_VMS.pm
+./usr/lib/perl5/ExtUtils/MM_Win32.pm
./usr/lib/perl5/ExtUtils/MakeMaker.pm
./usr/lib/perl5/ExtUtils/Manifest.pm
./usr/lib/perl5/ExtUtils/Miniperl.pm
@@ -482,18 +502,24 @@
./usr/lib/perl5/ExtUtils/testlib.pm
./usr/lib/perl5/ExtUtils/typemap
./usr/lib/perl5/ExtUtils/xsubpp
+./usr/lib/perl5/ExtUtils/xsubpp.cat1
./usr/lib/perl5/File
./usr/lib/perl5/File/Basename.pm
./usr/lib/perl5/File/CheckTree.pm
+./usr/lib/perl5/File/Compare.pm
./usr/lib/perl5/File/Copy.pm
+./usr/lib/perl5/File/DosGlob.pm
./usr/lib/perl5/File/Find.pm
./usr/lib/perl5/File/Path.pm
+./usr/lib/perl5/File/stat.pm
./usr/lib/perl5/FileCache.pm
+./usr/lib/perl5/FindBin.pm
./usr/lib/perl5/Getopt
./usr/lib/perl5/Getopt/Long.pm
./usr/lib/perl5/Getopt/Std.pm
./usr/lib/perl5/I18N
./usr/lib/perl5/I18N/Collate.pm
+./usr/lib/perl5/IO
./usr/lib/perl5/IPC
./usr/lib/perl5/IPC/Open2.pm
./usr/lib/perl5/IPC/Open3.pm
@@ -501,8 +527,13 @@
./usr/lib/perl5/Math/BigFloat.pm
./usr/lib/perl5/Math/BigInt.pm
./usr/lib/perl5/Math/Complex.pm
+./usr/lib/perl5/Math/Trig.pm
./usr/lib/perl5/Net
./usr/lib/perl5/Net/Ping.pm
+./usr/lib/perl5/Net/hostent.pm
+./usr/lib/perl5/Net/netent.pm
+./usr/lib/perl5/Net/protoent.pm
+./usr/lib/perl5/Net/servent.pm
./usr/lib/perl5/Pod
./usr/lib/perl5/Pod/Functions.pm
./usr/lib/perl5/Pod/Text.pm
@@ -529,24 +560,37 @@
./usr/lib/perl5/Text/Wrap.pm
./usr/lib/perl5/Tie
./usr/lib/perl5/Tie/Hash.pm
+./usr/lib/perl5/Tie/RefHash.pm
./usr/lib/perl5/Tie/Scalar.pm
./usr/lib/perl5/Tie/SubstrHash.pm
./usr/lib/perl5/Time
./usr/lib/perl5/Time/Local.pm
+./usr/lib/perl5/Time/gmtime.pm
+./usr/lib/perl5/Time/localtime.pm
+./usr/lib/perl5/Time/tm.pm
+./usr/lib/perl5/UNIVERSAL.pm
+./usr/lib/perl5/User
+./usr/lib/perl5/User/grent.pm
+./usr/lib/perl5/User/pwent.pm
./usr/lib/perl5/abbrev.pl
./usr/lib/perl5/assert.pl
./usr/lib/perl5/auto
-./usr/lib/perl5/auto/DynaLoader
-./usr/lib/perl5/auto/DynaLoader/autosplit.ix
-./usr/lib/perl5/auto/DynaLoader/dl_expandspec.al
-./usr/lib/perl5/auto/DynaLoader/dl_findfile.al
+./usr/lib/perl5/auto/Text
+./usr/lib/perl5/auto/Text/ParseWords
+./usr/lib/perl5/auto/Text/ParseWords/autosplit.ix
+./usr/lib/perl5/auto/Text/ParseWords/old_shellwords.al
+./usr/lib/perl5/auto/Text/ParseWords/quotewords.al
+./usr/lib/perl5/auto/Text/ParseWords/shellwords.al
+./usr/lib/perl5/autouse.pm
+./usr/lib/perl5/base.pm
./usr/lib/perl5/bigfloat.pl
./usr/lib/perl5/bigint.pl
./usr/lib/perl5/bigrat.pl
+./usr/lib/perl5/blib.pm
./usr/lib/perl5/cacheout.pl
-./usr/lib/perl5/chat2.inter
./usr/lib/perl5/chat2.pl
./usr/lib/perl5/complete.pl
+./usr/lib/perl5/constant.pm
./usr/lib/perl5/ctime.pl
./usr/lib/perl5/diagnostics.pm
./usr/lib/perl5/dotsh.pl
@@ -565,31 +609,44 @@
./usr/lib/perl5/integer.pm
./usr/lib/perl5/less.pm
./usr/lib/perl5/lib.pm
+./usr/lib/perl5/locale.pm
./usr/lib/perl5/look.pl
./usr/lib/perl5/newgetopt.pl
./usr/lib/perl5/open2.pl
./usr/lib/perl5/open3.pl
-./usr/lib/perl5/overload.pm
./usr/lib/perl5/perl5db.pl
./usr/lib/perl5/pod
./usr/lib/perl5/pod/perl.pod
+./usr/lib/perl5/pod/perlapio.pod
./usr/lib/perl5/pod/perlbook.pod
./usr/lib/perl5/pod/perlbot.pod
./usr/lib/perl5/pod/perlcall.pod
./usr/lib/perl5/pod/perldata.pod
./usr/lib/perl5/pod/perldebug.pod
+./usr/lib/perl5/pod/perldelta.pod
./usr/lib/perl5/pod/perldiag.pod
./usr/lib/perl5/pod/perldsc.pod
./usr/lib/perl5/pod/perlembed.pod
+./usr/lib/perl5/pod/perlfaq.pod
+./usr/lib/perl5/pod/perlfaq1.pod
+./usr/lib/perl5/pod/perlfaq2.pod
+./usr/lib/perl5/pod/perlfaq3.pod
+./usr/lib/perl5/pod/perlfaq4.pod
+./usr/lib/perl5/pod/perlfaq5.pod
+./usr/lib/perl5/pod/perlfaq6.pod
+./usr/lib/perl5/pod/perlfaq7.pod
+./usr/lib/perl5/pod/perlfaq8.pod
+./usr/lib/perl5/pod/perlfaq9.pod
./usr/lib/perl5/pod/perlform.pod
./usr/lib/perl5/pod/perlfunc.pod
./usr/lib/perl5/pod/perlguts.pod
./usr/lib/perl5/pod/perlipc.pod
+./usr/lib/perl5/pod/perllocale.pod
./usr/lib/perl5/pod/perllol.pod
./usr/lib/perl5/pod/perlmod.pod
+./usr/lib/perl5/pod/perlmodlib.pod
./usr/lib/perl5/pod/perlobj.pod
./usr/lib/perl5/pod/perlop.pod
-./usr/lib/perl5/pod/perlovl.pod
./usr/lib/perl5/pod/perlpod.pod
./usr/lib/perl5/pod/perlre.pod
./usr/lib/perl5/pod/perlref.pod
@@ -600,6 +657,7 @@
./usr/lib/perl5/pod/perlsyn.pod
./usr/lib/perl5/pod/perltie.pod
./usr/lib/perl5/pod/perltoc.pod
+./usr/lib/perl5/pod/perltoot.pod
./usr/lib/perl5/pod/perltrap.pod
./usr/lib/perl5/pod/perlvar.pod
./usr/lib/perl5/pod/perlxs.pod
@@ -608,7 +666,6 @@
./usr/lib/perl5/shellwords.pl
./usr/lib/perl5/sigtrap.pm
./usr/lib/perl5/site_perl
-./usr/lib/perl5/splain
./usr/lib/perl5/stat.pl
./usr/lib/perl5/strict.pm
./usr/lib/perl5/subs.pm
diff --git a/distrib/sets/lists/man/mi b/distrib/sets/lists/man/mi
index 58026311ff4..14b1cc4498b 100644
--- a/distrib/sets/lists/man/mi
+++ b/distrib/sets/lists/man/mi
@@ -107,6 +107,7 @@
./usr/share/man/cat1/bdes.0
./usr/share/man/cat1/bg.0
./usr/share/man/cat1/biff.0
+./usr/share/man/cat1/c2ph.0
./usr/share/man/cat1/cal.0
./usr/share/man/cat1/calendar.0
./usr/share/man/cat1/cap_mkdb.0
@@ -194,6 +195,8 @@
./usr/share/man/cat1/gzcat.0
./usr/share/man/cat1/gzexe.0
./usr/share/man/cat1/gzip.0
+./usr/share/man/cat1/h2ph.0
+./usr/share/man/cat1/h2xs.0
./usr/share/man/cat1/head.0
./usr/share/man/cat1/hexdump.0
./usr/share/man/cat1/history.0
@@ -289,23 +292,38 @@
./usr/share/man/cat1/patch.0
./usr/share/man/cat1/pax.0
./usr/share/man/cat1/perl.0
+./usr/share/man/cat1/perlapio.0
./usr/share/man/cat1/perlbook.0
./usr/share/man/cat1/perlbot.0
+./usr/share/man/cat1/perlbug.0
./usr/share/man/cat1/perlcall.0
./usr/share/man/cat1/perldata.0
./usr/share/man/cat1/perldebug.0
+./usr/share/man/cat1/perldelta.0
./usr/share/man/cat1/perldiag.0
+./usr/share/man/cat1/perldoc.0
./usr/share/man/cat1/perldsc.0
./usr/share/man/cat1/perlembed.0
+./usr/share/man/cat1/perlfaq.0
+./usr/share/man/cat1/perlfaq1.0
+./usr/share/man/cat1/perlfaq2.0
+./usr/share/man/cat1/perlfaq3.0
+./usr/share/man/cat1/perlfaq4.0
+./usr/share/man/cat1/perlfaq5.0
+./usr/share/man/cat1/perlfaq6.0
+./usr/share/man/cat1/perlfaq7.0
+./usr/share/man/cat1/perlfaq8.0
+./usr/share/man/cat1/perlfaq9.0
./usr/share/man/cat1/perlform.0
./usr/share/man/cat1/perlfunc.0
./usr/share/man/cat1/perlguts.0
./usr/share/man/cat1/perlipc.0
+./usr/share/man/cat1/perllocale.0
./usr/share/man/cat1/perllol.0
./usr/share/man/cat1/perlmod.0
+./usr/share/man/cat1/perlmodlib.0
./usr/share/man/cat1/perlobj.0
./usr/share/man/cat1/perlop.0
-./usr/share/man/cat1/perlovl.0
./usr/share/man/cat1/perlpod.0
./usr/share/man/cat1/perlre.0
./usr/share/man/cat1/perlref.0
@@ -316,6 +334,7 @@
./usr/share/man/cat1/perlsyn.0
./usr/share/man/cat1/perltie.0
./usr/share/man/cat1/perltoc.0
+./usr/share/man/cat1/perltoot.0
./usr/share/man/cat1/perltrap.0
./usr/share/man/cat1/perlvar.0
./usr/share/man/cat1/perlxs.0
@@ -325,12 +344,16 @@
./usr/share/man/cat1/pkg_create.0
./usr/share/man/cat1/pkg_delete.0
./usr/share/man/cat1/pkg_info.0
+./usr/share/man/cat1/pl2pm.0
+./usr/share/man/cat1/pod2html.0
+./usr/share/man/cat1/pod2man.0
./usr/share/man/cat1/popd.0
./usr/share/man/cat1/pr.0
./usr/share/man/cat1/praliases.0
./usr/share/man/cat1/printenv.0
./usr/share/man/cat1/printf.0
./usr/share/man/cat1/ps.0
+./usr/share/man/cat1/pstruct.0
./usr/share/man/cat1/pushd.0
./usr/share/man/cat1/pwd.0
./usr/share/man/cat1/quota.0
@@ -380,6 +403,7 @@
./usr/share/man/cat1/sleep.0
./usr/share/man/cat1/sort.0
./usr/share/man/cat1/source.0
+./usr/share/man/cat1/splain.0
./usr/share/man/cat1/split.0
./usr/share/man/cat1/startkey.0
./usr/share/man/cat1/stop.0
@@ -441,6 +465,7 @@
./usr/share/man/cat1/window.0
./usr/share/man/cat1/write.0
./usr/share/man/cat1/xargs.0
+./usr/share/man/cat1/xsubpp.0
./usr/share/man/cat1/yes.0
./usr/share/man/cat1/ypcat.0
./usr/share/man/cat1/ypmatch.0
diff --git a/distrib/sparc/floppies/inst-common/instbin-krb.conf b/distrib/sparc/floppies/inst-common/instbin-krb.conf
index 5020a93da87..4a41d1dd6bd 100644
--- a/distrib/sparc/floppies/inst-common/instbin-krb.conf
+++ b/distrib/sparc/floppies/inst-common/instbin-krb.conf
@@ -1,4 +1,4 @@
-# $OpenBSD: instbin-krb.conf,v 1.6 1997/09/17 15:43:16 deraadt Exp $
+# $OpenBSD: instbin-krb.conf,v 1.7 1997/12/02 02:31:01 deraadt Exp $
#
# kcbin.conf - unified binary for the kc floppy
#
@@ -10,7 +10,7 @@ progs cat chmod chown cp dd df disklabel ed expr fsck_ffs
progs ftp getopt
progs ifconfig init installboot less ln ls mkdir mknod mount mount_cd9660
progs mount_ffs mount_nfs mount_kernfs
-progs mv newfs pax pdksh ping pwd reboot rm route
+progs mv newfs pax ksh ping pwd reboot rm route
progs sed stty sync test tset umount
progs gzip
@@ -18,8 +18,8 @@ ln chown chgrp
ln fsck_ffs fsck
ln less more
ln pax tar
-ln pdksh sh
-ln pdksh -sh # init invokes the shell this way
+ln ksh sh
+ln ksh -sh # init invokes the shell this way
ln test [
ln reboot halt
diff --git a/distrib/sparc/floppies/inst-common/instbin.conf b/distrib/sparc/floppies/inst-common/instbin.conf
index 45fa28f40dc..4ab8442cce9 100644
--- a/distrib/sparc/floppies/inst-common/instbin.conf
+++ b/distrib/sparc/floppies/inst-common/instbin.conf
@@ -1,4 +1,4 @@
-# $OpenBSD: instbin.conf,v 1.14 1997/09/17 15:43:17 deraadt Exp $
+# $OpenBSD: instbin.conf,v 1.15 1997/12/02 02:31:04 deraadt Exp $
#
# kcbin.conf - unified binary for the kc floppy
#
@@ -10,7 +10,7 @@ progs cat chmod chown cp dd df disklabel ed expr fsck_ffs
progs ftp getopt
progs ifconfig init installboot less ln ls mkdir mknod mount mount_cd9660
progs mount_ffs mount_nfs mount_kernfs
-progs mv newfs pax pdksh ping pwd reboot rm route
+progs mv newfs pax ksh ping pwd reboot rm route
progs sed stty sync test tset umount
progs rsh gzip
@@ -18,8 +18,8 @@ ln chown chgrp
ln fsck_ffs fsck
ln less more
ln pax tar
-ln pdksh sh
-ln pdksh -sh # init invokes the shell this way
+ln ksh sh
+ln ksh -sh # init invokes the shell this way
ln test [
ln reboot halt