From d8e4d937baf994c7b38c2d9cca2fd9f1ff2413c6 Mon Sep 17 00:00:00 2001 From: tg Date: Sun, 21 Mar 2004 00:34:46 +0000 Subject: [PATCH] Initial revision --- Makefile.in | 330 ++++ acconfig.h | 185 ++ aclocal.m4 | 1365 ++++++++++++++ check-fd.c | 89 + check-pgrp.c | 101 + check-sigs.c | 255 +++ config.h.in | 360 ++++ configure | 4447 ++++++++++++++++++++++++++++++++++++++++++++ configure.in | 328 ++++ etc/ksh.kshrc | 209 +++ etc/profile | 310 +++ etc/sys_config.sh | 64 + install-sh | 119 ++ ksh.Man | 3532 +++++++++++++++++++++++++++++++++++ misc/Bugs | 652 +++++++ misc/ChangeLog.sjg | 49 + misc/Changes.jrm | 61 + misc/Changes.mlj | 44 + misc/Changes.pc | 28 + misc/README.sjg | 118 ++ misc/ReadMe.eg | 46 + misc/ReadMe.emacs | 88 + misc/ReadMe.jrm | 118 ++ mkinstalldirs | 35 + mkman | 44 + new-version.sh | 75 + os2/Makefile | 323 ++++ os2/NEWS.os2 | 106 ++ os2/README.os2 | 498 +++++ os2/config.cache | 91 + os2/config.h | 345 ++++ os2/config.status | 2 + os2/configure.cmd | 111 ++ os2/emacs.out | 132 ++ os2/kshrc.ksh | 118 ++ os2/make.sed | 44 + os2/os2.c | 264 +++ os2/os2bugs | 19 + os2/os2siglist.out | 24 + os2/th.cmd | 28 + sigact.c | 482 +++++ sigact.h | 129 ++ stamp-h.in | 1 + 43 files changed, 15769 insertions(+) create mode 100644 Makefile.in create mode 100644 acconfig.h create mode 100644 aclocal.m4 create mode 100644 check-fd.c create mode 100644 check-pgrp.c create mode 100644 check-sigs.c create mode 100644 config.h.in create mode 100644 configure create mode 100644 configure.in create mode 100644 etc/ksh.kshrc create mode 100644 etc/profile create mode 100644 etc/sys_config.sh create mode 100644 install-sh create mode 100644 ksh.Man create mode 100644 misc/Bugs create mode 100644 misc/ChangeLog.sjg create mode 100644 misc/Changes.jrm create mode 100644 misc/Changes.mlj create mode 100644 misc/Changes.pc create mode 100644 misc/README.sjg create mode 100644 misc/ReadMe.eg create mode 100644 misc/ReadMe.emacs create mode 100644 misc/ReadMe.jrm create mode 100644 mkinstalldirs create mode 100644 mkman create mode 100644 new-version.sh create mode 100644 os2/Makefile create mode 100644 os2/NEWS.os2 create mode 100644 os2/README.os2 create mode 100644 os2/config.cache create mode 100644 os2/config.h create mode 100644 os2/config.status create mode 100644 os2/configure.cmd create mode 100644 os2/emacs.out create mode 100644 os2/kshrc.ksh create mode 100644 os2/make.sed create mode 100644 os2/os2.c create mode 100644 os2/os2bugs create mode 100644 os2/os2siglist.out create mode 100644 os2/th.cmd create mode 100644 sigact.c create mode 100644 sigact.h create mode 100644 stamp-h.in diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 0000000..10d7b32 --- /dev/null +++ b/Makefile.in @@ -0,0 +1,330 @@ +# +# @configure_input@ +# + +srcdir = @srcdir@ +VPATH = @srcdir@ + +CC = @CC@ +CPP = @CPP@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ + +DEFS = @DEFS@ +LIBS = @LIBS@ + +CPPFLAGS = @CPPFLAGS@ +CFLAGS = @CFLAGS@ +LDSTATIC = @LDSTATIC@ +LDFLAGS = @LDFLAGS@ + +SHELL_PROG = @SHELL_PROG@ + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +transform=@program_transform_name@ + +bindir = $(exec_prefix)/bin +mandir = $(prefix)/man/man$(manext) +manext = 1 + +# Suffix for executables: nothing for unix, .exe for os/2. +exe_suffix=@ac_exe_suffix@ + +SHELL = /bin/sh + +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 sigact.c syn.c table.c trap.c \ + tree.c tty.c var.c version.c vi.c +OBJS = alloc.o c_ksh.o c_sh.o c_test.o c_ulimit.o edit.o emacs.o \ + eval.o exec.o expr.o history.o io.o jobs.o lex.o mail.o \ + main.o misc.o missing.o path.o shf.o sigact.o syn.o table.o trap.o \ + tree.o tty.o var.o version.o vi.o +HDRS = c_test.h edit.h expand.h ksh_dir.h ksh_limval.h ksh_stat.h ksh_time.h \ + ksh_times.h ksh_wait.h lex.h proto.h sh.h shf.h sigact.h \ + table.h tree.h tty.h +DISTFILES = $(SRCS) $(HDRS) ksh.Man Makefile.in configure.in \ + config.h.in conf-end.h acconfig.h aclocal.m4 emacs-gen.sh \ + mkinstalldirs install-sh new-version.sh siglist.in siglist.sh mkman \ + check-fd.c check-pgrp.c check-sigs.c \ + README NEWS CONTRIBUTORS LEGAL PROJECTS INSTALL NOTES BUG-REPORTS \ + IAFA-PACKAGE ChangeLog ChangeLog.0 configure stamp-h.in +# ETCFILES also disted, but handled differently +ETCFILES = etc/ksh.kshrc etc/profile etc/sys_config.sh +# MISCFILES also disted, but handled differently +MISCFILES = misc/ChangeLog.sjg misc/Changes.jrm misc/Changes.mlj \ + misc/Changes.pc misc/README.sjg misc/ReadMe.eg misc/ReadMe.emacs \ + misc/ReadMe.jrm misc/Bugs +# TESTFILES also disted, but handled differently +TESTFILES = tests/README tests/th tests/th-sh tests/alias.t tests/arith.t \ + tests/bksl-nl.t tests/brkcont.t tests/cdhist.t tests/eglob.t \ + tests/glob.t tests/heredoc.t tests/history.t tests/ifs.t \ + tests/integer.t tests/lineno.t tests/read.t tests/regress.t \ + tests/syntax.t tests/unclass1.t tests/unclass2.t \ + tests/version.t +# OS2FILES also disted, but handled differently +OS2FILES = os2/Makefile os2/config.h os2/config.status os2/configure.cmd \ + os2/emacs.out os2/kshrc.ksh os2/make.sed os2/os2.c os2/os2siglist.out \ + os2/README.os2 os2/NEWS.os2 os2/os2bugs os2/th.cmd os2/config.cache + +all: $(SHELL_PROG)$(exe_suffix) $(SHELL_PROG).1 + +# This shouldn't be first - some makes don't know about PRECIOUS and assume it +# is the default target. +.PRECIOUS: configure config.h.in Makefile config.status + +.c.o: + $(CC) -c $(CPPFLAGS) $(DEFS) -I. -I$(srcdir) $(CFLAGS) $< + +install: installdirs all + $(INSTALL_PROGRAM) $(SHELL_PROG)$(exe_suffix) $(bindir)/`echo $(SHELL_PROG)|sed '$(transform)'`$(exe_suffix) + -$(INSTALL_DATA) $(SHELL_PROG).1 $(mandir)/`echo $(SHELL_PROG)|sed '$(transform)'`.$(manext) + -@prog=$(bindir)/`echo $(SHELL_PROG)|sed '$(transform)'`$(exe_suffix);\ + test -f /etc/shells \ + && (grep "^$$prog\$$" /etc/shells > /dev/null \ + || echo \ +"NOTE: /etc/shells does not contain $$prog \ + you should add it if you want to set your shell to $(SHELL_PROG)") + +installdirs: + $(srcdir)/mkinstalldirs $(bindir) $(mandir) + +uninstall: + rm -f $(bindir)/`echo $(SHELL_PROG)|sed '$(transform)'`$(exe_suffix) + rm -f $(mandir)/`echo $(SHELL_PROG)|sed '$(transform)'`.$(manext) + +check test: + $(srcdir)/tests/th-sh $(srcdir)/tests/th -s $(srcdir)/tests -p ./$(SHELL_PROG)$(exe_suffix) -C pdksh,sh,ksh,posix,posix-upu $(TESTARGS) + +$(SHELL_PROG)$(exe_suffix): $(OBJS) + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) + +# two steps to prevent the creation of a bogus tmpksh.1 +$(SHELL_PROG).1: $(srcdir)/ksh.Man + $(srcdir)/mkman $(SHELL_PROG) $(srcdir)/ksh.Man > tmpksh.1 + mv tmpksh.1 $(SHELL_PROG).1 + +info: + @echo "No info (yet)" + +dvi: + +$(srcdir)/configure: configure.in aclocal.m4 + cd $(srcdir) && autoconf + +$(srcdir)/config.h.in: stamp-h.in +$(srcdir)/stamp-h.in: configure.in aclocal.m4 acconfig.h + cd $(srcdir) && autoheader + date > $(srcdir)/stamp-h.in + +config.h: stamp-h +stamp-h: config.h.in config.status + CONFIG_FILES="" CONFIG_HEADERS=config.h ./config.status + date > stamp-h + +Makefile: Makefile.in config.status + CONFIG_FILES=Makefile CONFIG_HEADERS= ./config.status + +config.status: configure + LDSTATIC="$(LDSTATIC)" ./config.status --recheck + +# two steps to prevent the creation of a bogus siglist.out +siglist.out: config.h sh.h siglist.in siglist.sh + $(srcdir)/siglist.sh "$(CPP) $(CPPFLAGS) $(DEFS) -I. -I$(srcdir)" < $(srcdir)/siglist.in > tmpsiglist.out + mv tmpsiglist.out siglist.out + +# two steps to prevent the creation of a bogus emacs.out +emacs.out: emacs.c + $(srcdir)/emacs-gen.sh $(srcdir)/emacs.c > tmpemacs.out + mv tmpemacs.out emacs.out + +debugtools: check-fd$(exe_suffix) check-sigs$(exe_suffix) \ + check-pgrp$(exe_suffix) + +check-fd.o check-pgrp.o check-sigs.o: config.h +check-fd$(exe_suffix): check-fd.o + $(CC) $(LDFLAGS) -o $@ check-fd.o $(LIBS) + +check-pgrp$(exe_suffix): check-pgrp.o + $(CC) $(LDFLAGS) -o $@ check-pgrp.o $(LIBS) + +check-sigs$(exe_suffix): check-sigs.o + $(CC) $(LDFLAGS) -o $@ check-sigs.o $(LIBS) + +TAGS: $(SRCS) $(HDRS) + cd $(srcdir) && etags $(SRCS) $(HDRS) + +tags: $(SRCS) $(HDRS) + cd $(srcdir) && ctags -wt $(SRCS) $(HDRS) + +clean: + rm -f ksh$(exe_suffix) sh$(exe_suffix) ksh.1 sh.1 $(OBJS) siglist.out \ + emacs.out core a.out mon.out gmon.out \ + version.c.bak Makefile.bak Makefile.tmp check-fd$(exe_suffix) \ + check-pgrp$(exe_suffix) check-sigs$(exe_suffix) + +mostlyclean: clean + +distclean: clean + rm -f Makefile config.h stamp-h config.status config.log config.cache \ + tags TAGS *~ + +realclean: distclean + +dist: $(DISTFILES) $(ETCFILES) $(MISCFILES) $(TESTFILES) $(OS2FILES) + cd $(srcdir) && \ + { \ + ./new-version.sh; \ + FNAME=pdksh-`sed -e '/"@(.)/!d' \ + -e 's/[^0-9]*\([0-9.]*\).*/\1/' -e q version.c`; \ + if test `echo $$FNAME|tr . ' '|wc -w|sed 's/[ ]*//g'` -gt 3; \ + then \ + FNAME=`echo $$FNAME | sed 's/pdksh-/pdksh-unstable-/'`; \ + fi; \ + echo Creating version $$FNAME; \ + rm -rf $$FNAME; \ + mkdir $$FNAME $$FNAME/etc $$FNAME/misc $$FNAME/tests $$FNAME/os2; \ + cp -p $(DISTFILES) $$FNAME; \ + cp -p $(ETCFILES) $$FNAME/etc; \ + cp -p $(MISCFILES) $$FNAME/misc; \ + cp -p $(TESTFILES) $$FNAME/tests; \ + cp -p $(OS2FILES) $$FNAME/os2; \ + ./emacs-gen.sh emacs.c > os2/emacs.out; \ + test -x ./Dist-fixup && ./Dist-fixup $$FNAME; \ + sed -f os2/make.sed < $$FNAME/Makefile.in > $$FNAME/os2/Makefile; \ + chmod -R a+rX,u+w,og-w $$FNAME; \ + tar chzf $$FNAME.tar.gz $$FNAME; \ + find $$FNAME -print | xargs pathchk -p; \ + } + +depend: $(SRCS) + sed -n '1,/[ ]PUT ANYTHING BELOW THIS LINE/p' < Makefile > Makefile.tmp + srcs=; for i in $(SRCS) ; do srcs="$$srcs $(srcdir)/$$i"; done; \ + $(CC) -M $(DEFS) -I. -I$(srcdir) $(CFLAGS) $$srcs | \ + sed -e 's?[ ]/[^ ]*??g' -e 's?[ ]./? ?g' \ + -e 's?[ ]$(srcdir)//*? ?g' -e 's?^$(srcdir)//*??' \ + -e '/^[ ]*\\[ ]*$$/d' -e '/^[^:]*:[ ]*$$/d' \ + -e 's/^\([ ]*\)$$/ sh.h/' \ + >> Makefile.tmp + mv Makefile.tmp Makefile + @echo 'Make depend done (stopping make)'; false + +# DON'T PUT ANYTHING BELOW THIS LINE (and don't delete it - its for make depend) +alloc.o: alloc.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h +c_ksh.o: c_ksh.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h ksh_stat.h \ + sh.h +c_sh.o: c_sh.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h ksh_stat.h ksh_time.h \ + ksh_times.h \ + sh.h +c_test.o: c_test.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h ksh_stat.h c_test.h +c_ulimit.o: c_ulimit.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h ksh_time.h \ + sh.h +edit.o: edit.c config.h conf-end.h sh.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h tty.h \ + edit.h \ + ksh_stat.h +emacs.o: emacs.c config.h conf-end.h sh.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h ksh_stat.h ksh_dir.h \ + edit.h emacs.out +eval.o: eval.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h \ + ksh_dir.h \ + ksh_stat.h +exec.o: exec.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h c_test.h \ + ksh_stat.h +expr.o: expr.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h \ + sh.h +history.o: history.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h ksh_stat.h +io.o: io.c \ + sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h ksh_stat.h +jobs.o: jobs.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h ksh_stat.h ksh_wait.h \ + ksh_times.h ksh_time.h \ + tty.h \ + sh.h +lex.o: lex.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h \ + sh.h +mail.o: mail.c config.h conf-end.h sh.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h ksh_stat.h ksh_time.h \ + sh.h +main.o: main.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h ksh_stat.h ksh_time.h \ + sh.h +misc.o: misc.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h \ + sh.h +missing.o: missing.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h ksh_stat.h ksh_dir.h \ + ksh_time.h \ + ksh_times.h \ + sh.h +path.o: path.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h ksh_stat.h +shf.o: shf.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h ksh_stat.h ksh_limval.h \ + sh.h +sigact.o: sigact.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h +syn.o: syn.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h c_test.h +table.o: table.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h +trap.o: trap.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h siglist.out +tree.o: tree.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h +tty.o: tty.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h ksh_stat.h tty.h \ + sh.h +var.o: var.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h ksh_time.h \ + ksh_limval.h \ + ksh_stat.h \ + sh.h +version.o: version.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h +vi.o: vi.c config.h conf-end.h sh.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h \ + ksh_stat.h edit.h diff --git a/acconfig.h b/acconfig.h new file mode 100644 index 0000000..9d83ece --- /dev/null +++ b/acconfig.h @@ -0,0 +1,185 @@ +/* + * 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 + +@TOP@ + +/* 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 ). */ +#undef RETSIGVAL + +/* Define if you have posix signal routines (sigaction(), et. al.) */ +#undef POSIX_SIGNALS + +/* 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 */ +#undef POSIX_PGRP + +/* 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 */ +#undef HAVE_PROTOTYPES + +/* Define if C compiler groks __attribute__((...)) (const, noreturn, format) */ +#undef HAVE_GCC_FUNC_ATTR + +/* Define to 32-bit signed integer type */ +#undef INT32 + +/* Define to 32-bit signed integer type if 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 */ +#undef TIME_DECLARED + +/* Define to `unsigned' if doesn't define */ +#undef sigset_t + +/* Define if sys_errlist[] and sys_nerr are in the C library */ +#undef HAVE_SYS_ERRLIST + +/* Define if sys_errlist[] and sys_nerr are defined in */ +#undef SYS_ERRLIST_DECLARED + +/* Define if sys_siglist[] is in the C library */ +#undef HAVE_SYS_SIGLIST + +/* Define if you have a sane header file */ +#undef HAVE_TERMIOS_H + +/* Define if you can include with */ +#undef SYS_IOCTL_WITH_TERMIOS + +/* Define if you can include with */ +#undef SYS_IOCTL_WITH_TERMIO + +/* Define if you have a memset() function in your C library */ +#undef HAVE_MEMSET + +/* Define if you have a memmove() function in your C library */ +#undef HAVE_MEMMOVE + +/* 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 */ +#undef HAVE_LSTAT + +/* Define if you have a sane 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 */ +#undef POSIX_SYS_WAIT + +/* Define if your OS maps references to /dev/fd/n to file descriptor n */ +#undef HAVE_DEV_FD + +/* Define if your C library's getwd/getcwd function dumps core in unreadable + * directories. */ +#undef HPUX_GETWD_BUG + +/* ------- ------ ----- ---- --- -- - - -- --- ---- ----- ------ ------- */ +/* Defines from here on down are enable/disable options to configure */ + +/* Default PATH (see comments in configure.in for more details) */ +#undef DEFAULT_PATH + +/* Include ksh features? (see comments in configure.in for more details) */ +#undef KSH + +/* Include emacs editing? (see comments in configure.in for more details) */ +#undef EMACS + +/* Include vi editing? (see comments in configure.in for more details) */ +#undef VI + +/* Include job control? (see comments in configure.in for more details) */ +#undef JOBS + +/* Include brace-expansion? (see comments in configure.in for more details) */ +#undef BRACE_EXPAND + +/* Include any history? (see comments in configure.in for more details) */ +#undef HISTORY + +/* 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 + +@BOTTOM@ + +/* 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/aclocal.m4 b/aclocal.m4 new file mode 100644 index 0000000..43731c5 --- /dev/null +++ b/aclocal.m4 @@ -0,0 +1,1365 @@ +dnl Copyright (C) 1996, Memorial University of Newfoundland. +dnl This file is covered by the GNU General Public License, version 2, see +dnl the file misc/COPYING for details. +dnl +dnl This file is covered by the GPL 'cause it contains some modified versions +dnl of autoconf's macros, in particular: +dnl AC_FUNC_MMAP AC_LANG_C AC_LANG_CPLUXPLUS AC_TRY_RUN KSH_HEADER_SYS_WAIT +dnl AC_HEADER_STAT AC_PROG_CC +dnl +dnl +dnl Like AC_CHECK_TYPE(), only +dnl - user gets to specify header file(s) in addition to the default +dnl headers ( and ) +dnl - user gets to specify the message +dnl - word boundary checks are put at beginning/end of pattern +dnl (ie, \) +dnl - default argument is optional +dnl uses ac_cv_type_X 'cause this is used in other autoconf macros... +dnl KSH_CHECK_H_TYPE(type, message, header files, default) +AC_DEFUN(KSH_CHECK_H_TYPE, + [AC_CACHE_CHECK($2, ac_cv_type_$1, + [AC_EGREP_CPP([(^|[^a-zA-Z0-9_])]$1[([^a-zA-Z0-9_]|\$)], + [#include +#if STDC_HEADERS +#include +#endif +$3 + ], ac_cv_type_$1=yes, ac_cv_type_$1=no)]) + ifelse($#, 4, [if test $ac_cv_type_$1 = no; then + AC_DEFINE($1, $4) + fi + ])dnl + ])dnl +dnl +dnl +dnl +dnl Check for memmove and if not found, check for bcopy. AC_CHECK_FUNCS() +dnl not used 'cause it confuses some compilers that have memmove/bcopy builtin; +dnl Also want to check if the function deals with overlapping src/dst properly. +AC_DEFUN(KSH_MEMMOVE, + [AC_CACHE_CHECK(for working memmove, ksh_cv_func_memmove, + [AC_TRY_RUN([ +#ifdef HAVE_STRING_H +# include +#else +# include +#endif +#ifdef HAVE_MEMORY_H +# include +#endif + int + main() + { + char buf[16]; + strcpy(buf, "abcdefABCDEF"); + memmove(buf + 4, buf, 6); + if (strcmp(buf, "abcdabcdefEF")) + exit(1); + memmove(buf, buf + 4, 6); + if (strcmp(buf, "abcdefcdefEF")) + exit(2); + exit(0); + return 0; + }], + ksh_cv_func_memmove=yes, ksh_cv_func_memmove=no, + AC_MSG_WARN(assuming memmove broken); ksh_cv_func_memmove=no)]) + if test $ksh_cv_func_memmove = yes; then + AC_DEFINE(HAVE_MEMMOVE) + else + AC_CACHE_CHECK(for working bcopy, ksh_cv_func_bcopy, + [AC_TRY_RUN([ +#ifdef HAVE_STRING_H +# include +#else +# include +#endif +#ifdef HAVE_MEMORY_H +# include +#endif + int + main() + { + char buf[16]; + strcpy(buf, "abcdefABCDEF"); + bcopy(buf, buf + 4, 6); + if (strcmp(buf, "abcdabcdefEF")) + exit(1); + bcopy(buf + 4, buf, 6); + if (strcmp(buf, "abcdefcdefEF")) + exit(2); + exit(0); + }], + ksh_cv_func_bcopy=yes, ksh_cv_func_bcopy=no, + AC_MSG_WARN(assuming bcopy broken); ksh_cv_func_bcopy=no)]) + if test $ksh_cv_func_bcopy = yes; then + AC_DEFINE(HAVE_BCOPY) + fi + fi + ])dnl +dnl +dnl +dnl +dnl Check for sigsetjmp()/siglongjmp() and _setjmp()/_longjmp() pairs. +dnl Can't use simple library check as QNX 422 has _setjmp() but not _longjmp() +dnl (go figure). +AC_DEFUN(KSH_SETJMP, + [AC_CACHE_CHECK(for sigsetjmp()/siglongjmp(), ksh_cv_func_sigsetjmp, + [AC_TRY_LINK([], [sigsetjmp(); siglongjmp()], + ksh_cv_func_sigsetjmp=yes, ksh_cv_func_sigsetjmp=no)]) + if test $ksh_cv_func_sigsetjmp = yes; then + AC_DEFINE(HAVE_SIGSETJMP) + else + AC_CACHE_CHECK(for _setjmp()/_longjmp(), ksh_cv_func__setjmp, + [AC_TRY_LINK([], [_setjmp(); _longjmp();], + ksh_cv_func__setjmp=yes, ksh_cv_func__setjmp=no)]) + if test $ksh_cv_func__setjmp = yes; then + AC_DEFINE(HAVE__SETJMP) + fi + fi + ])dnl +dnl +dnl +dnl +dnl Check for memset function. AC_CHECK_FUNCS() not used 'cause it confuses +dnl some compilers that have memset builtin. +AC_DEFUN(KSH_MEMSET, + [AC_CACHE_CHECK(for memset, ksh_cv_func_memset, + [AC_TRY_LINK([ +#ifdef HAVE_STRING_H +# include +#else +# include +#endif +#ifdef HAVE_MEMORY_H +# include +#endif + ], [ + char buf[16]; memset(buf, 'x', 7); printf("%7s", buf);], + ksh_cv_func_memset=yes, ksh_cv_func_memset=no)]) + if test $ksh_cv_func_memset = yes; then + AC_DEFINE(HAVE_MEMSET) + fi + ])dnl +dnl +dnl +dnl +dnl Check for rlim_t in a few places, and if not found, figure out the +dnl size rlim_t should be by looking at struct rlimit.rlim_cur. +AC_DEFUN(KSH_RLIM_CHECK, + [KSH_CHECK_H_TYPE(rlim_t, for rlim_t in and , + [#ifdef HAVE_SYS_RESOURCE_H +#include +#endif])dnl + if test $ac_cv_type_rlim_t = no; then + AC_MSG_CHECKING(what to set rlim_t to) + if test $ac_cv_header_sys_resource_h = yes; then + AC_CACHE_VAL(ksh_cv_rlim_check, + [AC_TRY_RUN([ +#include +#include +#include + main() + { + struct rlimit rl; + if (sizeof(rl.rlim_cur) == sizeof(quad_t)) + exit(0); + exit(1); + } + ], ksh_cv_rlim_check=quad_t, ksh_cv_rlim_check=long, + AC_MSG_ERROR(cannot determine type for rlimt_t when cross compiling) + )])dnl + else + ksh_cv_rlim_check=long + fi + AC_MSG_RESULT($ksh_cv_rlim_check) + AC_DEFINE_UNQUOTED(rlim_t, $ksh_cv_rlim_check) + fi + ])dnl +dnl +dnl +dnl +AC_DEFUN(KSH_DEV_FD, + [AC_CACHE_CHECK(if you have /dev/fd/n, ksh_cv_dev_fd, + [AC_TRY_RUN([ +#include +#include +#include + main() + { + struct stat s1, s2; + FILE *fp1, *fp2; + char *file = "conftest.file"; + char devfd[32]; + + if (!(fp1 = fopen(file, "w"))) + exit(1); + if (fstat(fileno(fp1), &s1) < 0) + exit(2); + sprintf(devfd, "/dev/fd/%d", fileno(fp1)); + if (!(fp2 = fopen(devfd, "w"))) + exit(3); + if (fstat(fileno(fp2), &s2) < 0) + exit(4); + if (s1.st_dev != s2.st_dev || s1.st_ino != s2.st_ino) + exit(5); + exit(0); + } + ], ksh_cv_dev_fd=yes, ksh_cv_dev_fd=no, + AC_MSG_WARN(cannot determine if you have /dev/fd support, assuming not) + ksh_cv_dev_fd=no)]) + if test $ksh_cv_dev_fd = yes; then + AC_DEFINE(HAVE_DEV_FD) + fi + ])dnl +dnl +dnl +dnl +dnl Check for sys_siglist[] declaration and existence. +AC_DEFUN(KSH_SYS_SIGLIST, + [AC_DECL_SYS_SIGLIST + if test ac_cv_decl_sys_siglist = yes; then + AC_DEFINE(HAVE_SYS_SIGLIST) + else + AC_CACHE_CHECK(for sys_siglist in library, ksh_cv_var_sys_siglist, + [AC_TRY_LINK(, [ + extern char *sys_siglist[]; + char *p = sys_siglist[2]; + if (p) + return 12; + ], ksh_cv_var_sys_siglist=yes, ksh_cv_var_sys_siglist=no)]) + if test $ksh_cv_var_sys_siglist = yes; then + AC_DEFINE(HAVE_SYS_SIGLIST) + fi + fi + ])dnl +dnl +dnl +dnl +dnl Check for sys_errlist[] declaration and existence. +AC_DEFUN(KSH_SYS_ERRLIST, + [AC_CACHE_CHECK(for sys_errlist declaration in errno.h, ksh_cv_decl_sys_errlist, + [AC_TRY_COMPILE([#include ], + [char *msg = *(sys_errlist + 1); if (msg && *msg) return 12; ], + ksh_cv_decl_sys_errlist=yes, ksh_cv_decl_sys_errlist=no)]) + if test $ksh_cv_decl_sys_errlist = yes; then + AC_DEFINE(SYS_ERRLIST_DECLARED) + AC_DEFINE(HAVE_SYS_ERRLIST) + else + AC_CACHE_CHECK(for sys_errlist in library, ksh_cv_var_sys_errlist, + [AC_TRY_LINK(, [ + extern char *sys_errlist[]; + extern int sys_nerr; + char *p; + p = sys_errlist[sys_nerr - 1]; + if (p) return 12; + ], ksh_cv_var_sys_errlist=yes, ksh_cv_var_sys_errlist=no)]) + if test $ksh_cv_var_sys_errlist = yes; then + AC_DEFINE(HAVE_SYS_ERRLIST) + fi + fi + ])dnl +dnl +dnl +dnl +dnl Check if time() declared in time.h +AC_DEFUN(KSH_TIME_DECLARED, + [AC_CACHE_CHECK(time() declaration in time.h, ksh_cv_time_delcared, + [AC_TRY_COMPILE([#include +#include ], [time_t (*f)() = time; if (f) return 12;], + ksh_cv_time_delcared=yes, ksh_cv_time_delcared=no)]) + if test $ksh_cv_time_delcared = yes; then + AC_DEFINE(TIME_DECLARED) + fi + ])dnl +dnl +dnl +dnl +dnl Check for working times (ie, it exists and doesn't always return 0). +dnl Defines TIMES_BROKEN if it doesn't exist or if it always returns 0 +dnl (also checks for existance of getrusage if times doesn't work). +dnl XXX: requires clock_t to be typedefed/defined... +AC_DEFUN(KSH_TIMES_CHECK, + [AC_CACHE_CHECK(if times() is present/working, ksh_cv_func_times_ok, + [AC_TRY_RUN([ +#include +#include +/* if missing, clock_t is defined to be INT32 */ +#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 */ + main() + { + extern clock_t times(); + struct tms tms; + times(&tms); + sleep(1); + if (times(&tms) == 0) + exit(1); + exit(0); + } + ], ksh_cv_func_times_ok=yes, ksh_cv_func_times_ok=no, + AC_MSG_ERROR(cannot determine if times works when cross compiling) + )]) + if test $ksh_cv_func_times_ok = no; then + AC_DEFINE(TIMES_BROKEN) + AC_CHECK_FUNCS(getrusage) + fi + ])dnl +dnl +dnl +dnl +AC_DEFUN(KSH_C_VOID, + [AC_CACHE_CHECK(if compiler understands void, ksh_cv_c_void, + [AC_TRY_COMPILE( + [ + void foo() { } + /* Some compilers (old pcc ones) like "void *a;", but a can't be used */ + void *bar(a) void *a; { int *b = (int *) a; *b = 1; return a; } + ], , ksh_cv_c_void=yes, ksh_cv_c_void=no)]) + if test $ksh_cv_c_void = yes; then + : + else + AC_DEFINE(void, char) + fi + ])dnl +dnl +dnl +dnl +dnl Early MIPS compilers (used in Ultrix 4.2) don't like +dnl "int x; int *volatile a = &x; *a = 0;" +AC_DEFUN(KSH_C_VOLATILE, + [AC_CACHE_CHECK(if compiler understands volatile, ksh_cv_c_volatile, + [AC_TRY_COMPILE([int x, y, z;], + [volatile int a; int * volatile b = x ? &y : &z; + /* Older MIPS compilers (eg., in Ultrix 4.2) don't like *b = 0 */ + *b = 0;], ksh_cv_c_volatile=yes, ksh_cv_c_volatile=no)]) + if test $ksh_cv_c_volatile = yes; then + : + else + AC_DEFINE(volatile, ) + fi + ])dnl +dnl +dnl +dnl +dnl Check if function prototypes work (including stdc vararg prototypes) +AC_DEFUN(KSH_C_PROTOTYPES, + [AC_CACHE_CHECK(if compiler understands prototypes, ksh_cv_c_prototypes, + [AC_TRY_COMPILE([ +#include +void foo(char *fmt, ...); +int bar(int a, char b, char *c); +int bar(a, b, c) int a; char b; char *c; +{ foo("%d%c%s\n", a, b, c); return a + b + *c; } +void foo(char *fmt, ...) { va_list a; va_start(a, fmt); va_end(a); } + ], , ksh_cv_c_prototypes=yes, ksh_cv_c_prototypes=no)]) + if test $ksh_cv_c_prototypes = yes; then + AC_DEFINE(HAVE_PROTOTYPES) + fi + ])dnl +dnl +dnl +dnl +dnl Check if C compiler understands gcc's __attribute((...)). +dnl checks for noreturn, const, and format(type,fmt,param), also checks +dnl that the compiler doesn't die when it sees an unknown attribute (this +dnl isn't perfect since gcc doesn't parse unknown attributes with parameters) +AC_DEFUN(KSH_C_FUNC_ATTR, + [AC_CACHE_CHECK(if C compiler groks __attribute__(( .. )), ksh_cv_c_func_attr, + [AC_TRY_COMPILE([ +#include +void test_fmt(char *fmt, ...) __attribute__((format(printf, 1, 2))); +void test_fmt(char *fmt, ...) { return; } +int test_cnst(int) __attribute__((const)); +int test_cnst(int x) { return x + 1; } +void test_nr() __attribute__((noreturn)); +void test_nr() { exit(1); } +void test_uk() __attribute__((blah)); +void test_uk() { return; } + ], [test_nr("%d", 10); test_cnst(2); test_uk(); test_nr(); ], + ksh_cv_c_func_attr=yes, ksh_cv_c_func_attr=no)]) + if test $ksh_cv_c_func_attr = yes; then + AC_DEFINE(HAVE_GCC_FUNC_ATTR) + fi + ])dnl +dnl +dnl +dnl +dnl Check if dup2() does not clear the close on exec flag +AC_DEFUN(KSH_DUP2_CLEXEC_CHECK, + [AC_CACHE_CHECK([if dup2() works (ie, resets the close-on-exec flag)], ksh_cv_dup2_clexec_ok, + [AC_TRY_RUN([ +#include +#ifdef HAVE_FCNTL_H +# include +#endif /* HAVE_FCNTL_H */ +#ifndef F_GETFD +# define F_GETFD 1 +#endif +#ifndef F_SETFD +# define F_SETFD 2 +#endif +#ifndef O_RDONLY +# define O_RDONLY 0 +#endif +/* On some systems (Ultrix 2.1..4.2 (and more?)), dup2() does not clear + the close on exec flag */ +main() +{ + int fd1, fd2; + fd1 = open("/dev/null", O_RDONLY); + if (fcntl(fd1, F_SETFD, 1) < 0) + exit(1); + fd2 = dup2(fd1, fd1 + 1); + if (fd2 < 0) + exit(2); + exit(fcntl(fd2, F_GETFD, 0) == 0 ? 0 : 3); +} + ], ksh_cv_dup2_clexec_ok=yes, ksh_cv_dup2_clexec_ok=no, + AC_MSG_WARN(cannot test if dup2 is broken when cross compiling - assuming it is) + ksh_cv_dup2_clexec_ok=no)]) + if test $ksh_cv_dup2_clexec_ok = no; then + AC_DEFINE(DUP2_BROKEN) + fi + ])dnl +dnl +dnl +dnl +dnl Check type of signal routines (posix, 4.2bsd, 4.1bsd or v7) +AC_DEFUN(KSH_SIGNAL_CHECK, + [AC_CACHE_CHECK(flavour of signal routines, ksh_cv_signal_check, + [AC_TRY_LINK([#include ], [ + sigset_t ss; + struct sigaction sa; + sigemptyset(&ss); sigsuspend(&ss); + sigaction(SIGINT, &sa, (struct sigaction *) 0); + sigprocmask(SIG_BLOCK, &ss, (sigset_t *) 0); + ], ksh_cv_signal_check=posix, + AC_TRY_LINK([#include ], [ + int mask = sigmask(SIGINT); + sigsetmask(mask); sigblock(mask); sigpause(mask); + ], ksh_cv_signal_check=bsd42, + AC_TRY_LINK([#include + RETSIGTYPE foo() { }], + [ + int mask = sigmask(SIGINT); + sigset(SIGINT, foo); sigrelse(SIGINT); + sighold(SIGINT); sigpause(SIGINT); + ], ksh_cv_signal_check=bsd41, ksh_cv_signal_check=v7)))]) + if test $ksh_cv_signal_check = posix; then + AC_DEFINE(POSIX_SIGNALS) + else + AC_DEFINE(USE_FAKE_SIGACT) + if test $ksh_cv_signal_check = bsd42; then + AC_DEFINE(BSD42_SIGNALS) + elif test $ksh_cv_signal_check = bsd41; then + AC_DEFINE(BSD41_SIGNALS) + AC_CACHE_CHECK(if signals interrupt read(), ksh_cv_signals_interrupt, + [AC_TRY_RUN([ +#include +#include + + extern int errno; + int flag = 0; + + RETSIGTYPE + catcher(int sig) + { + flag = 1; + return RETSIGVAL; + } + + int + main() + { + int pid; + int fdc[2]; /* child writes to parent */ + int fdp[2]; /* parent writes to child */ + char buf; + int nread; + + if (pipe(fdc) < 0) + exit(1); + if (pipe(fdp) < 0) + exit(2); + if ((pid = fork()) < 0) + exit(3); + if (pid == 0) { + close(fdc[0]); + close(fdp[1]); + if (read(fdp[0], &buf, 1) != 0) + exit(10); + sleep(1); /* let parent into read */ + if (kill(getppid(), SIGALRM) < 0) + exit(11); + sleep(1); /* ensure parent gets to run */ + write(fdc[1], "1", 1); + close(fdc[1]); + exit(0); + } + close(fdc[1]); + close(fdp[0]); + + /* Use native routines for test as this is what the shell + * will be using... + */ +#ifdef POSIX_SIGNALS + { + struct sigaction sa, osa; + sa.sa_handler = catcher; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sigaction(SIGALRM, &sa, &osa); + } +#else /* POSIX_SIGNALS */ +# ifdef BSD42_SIGNALS + { + struct sigvec vec, ovec; + vec.sv_handler = catcher; + vec.sv_mask = 0; + vec.sv_flags = 0; +# ifdef SV_INTERRUPT + vec.sv_flags |= SV_INTERRUPT; +# endif /* SV_INTERRUPT */ + sigvec(SIGALRM, &vec, &ovec); + } +# else /* BSD42_SIGNALS */ +# ifdef BSD41_SIGNALS + sigset(SIGALRM, catcher); +# else /* BSD41_SIGNALS */ +# ifdef V7_SIGNALS + signal(SIGALRM, catcher); +# else /* V7_SIGNALS */ + what kind of signals do you have? +# endif /* V7_SIGNALS */ +# endif /* BSD41_SIGNALS */ +# endif /* BSD42_SIGNALS */ +#endif /* POSIX_SIGNALS */ + close(fdp[1]); /* start child */ + nread = read(fdc[0], &buf, 1); + if (nread == 0) + exit(4); + if (nread > 0) + exit(5); + if (errno != EINTR) + exit(6); + if (!flag) + exit(7); + exit(0); + return 0; + } + ], ksh_cv_signals_interrupt=yes, ksh_cv_signals_interrupt=no, + AC_MSG_ERROR(cannot determine if signals interrupt read() when cross compiling) + )]) + if test $ksh_cv_signals_interrupt = no ; then + AC_DEFINE(SIGNALS_DONT_INTERRUPT) + fi + else + AC_DEFINE(V7_SIGNALS) + fi + fi + ])dnl +dnl +dnl +dnl +dnl What kind of process groups: POSIX, BSD, SYSV or none +dnl BSD uses setpgrp(pid, pgrp), getpgrp(pid) +dnl POSIX uses setpid(pid, pgrp), getpgrp(void) +dnl SYSV uses setpgrp(void), getpgrp(void) +dnl Checks for BSD first since the posix test may succeed on BSDish systems +dnl (depends on what random value gets passed to getpgrp()). +AC_DEFUN(KSH_PGRP_CHECK, + [AC_CACHE_CHECK(flavour of pgrp routines, ksh_cv_pgrp_check, + [AC_TRY_RUN([ +/* Check for BSD process groups */ +#include +#ifdef HAVE_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ + main() + { + int ecode = 0, child = fork(); + if (child < 0) + exit(1); + if (child == 0) { + signal(SIGTERM, SIG_DFL); /* just to make sure */ + sleep(10); + exit(9); + } + if (setpgrp(child, child) < 0) + ecode = 2; + else if (getpgrp(child) != child) + ecode = 3; + kill(child, SIGTERM); + exit(ecode); + } + ], ksh_cv_pgrp_check=bsd, + [AC_TRY_RUN([ +/* Check for POSIX process groups */ +#ifdef HAVE_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ + main() + { + int child; + int n, p1[2], p2[2]; + char buf[1]; + if (pipe(p1) < 0 || pipe(p2) < 0) + exit(1); + if ((child = fork()) < 0) + exit(2); + if (child == 0) { + n = read(p1[0], buf, sizeof(buf)); /* wait for parent to setpgid */ + buf[0] = (n != 1 ? 10 : (getpgrp() != getpid() ? 11 : 0)); + if (write(p2[1], buf, sizeof(buf)) != 1) + exit(12); + exit(0); + } + if (setpgid(child, child) < 0) + exit(3); + if (write(p1[1], buf, 1) != 1) + exit(4); + if (read(p2[0], buf, 1) != 1) + exit(5); + exit((int) buf[0]); + } + ], ksh_cv_pgrp_check=posix, + [AC_TRY_RUN([ +/* Check for SYSV process groups */ +#ifdef HAVE_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ + main() + { + int child; + int n, p[2]; + char buf[1]; + if (pipe(p) < 0) + exit(1); + if ((child = fork()) < 0) + exit(2); + if (child == 0) { + buf[0] = (setpgrp() < 0 ? 10 : (getpgrp() != getpid() ? 11 : 0)); + if (write(p[1], buf, sizeof(buf)) != 1) + exit(11); + exit(0); + } + if (read(p[0], buf, 1) != 1) + exit(3); + exit((int) buf[0]); + } + ], ksh_cv_pgrp_check=sysv, ksh_cv_pgrp_check=none, + AC_MSG_ERROR(cannot taste pgrp routines when cross compiling))], + AC_MSG_ERROR(cannot taste pgrp routines when cross compiling))], + AC_MSG_ERROR(cannot taste pgrp routines when cross compiling))]) + if test $ksh_cv_pgrp_check = bsd; then + AC_DEFINE(BSD_PGRP) + elif test $ksh_cv_pgrp_check = posix; then + AC_DEFINE(POSIX_PGRP) + elif test $ksh_cv_pgrp_check = sysv; then + AC_DEFINE(SYSV_PGRP) + else + AC_DEFINE(NO_PGRP) + fi + ])dnl +dnl +dnl +dnl +dnl Check if the pgrp of setpgrp() can't be the pid of a zombie process. +dnl On some systems, the kernel doesn't count zombie processes when checking +dnl if a process group is valid, which can cause problems in creating the +dnl pipeline "cmd1 | cmd2": if cmd1 can die (and go into the zombie state) +dnl before cmd2 is started, the kernel doesn't allow the setpgrp() for cmd2 +dnl to succeed. This test defines NEED_PGRP_SYNC if the kernel has this bug. +dnl (pgrp_sync test doesn't mean much if don't have bsd or posix pgrps) +AC_DEFUN(KSH_PGRP_SYNC, + [AC_REQUIRE([KSH_PGRP_CHECK])dnl + if test $ksh_cv_pgrp_check = bsd || test $ksh_cv_pgrp_check = posix ; then + AC_CACHE_CHECK(if process group synchronization is required, ksh_cv_need_pgrp_sync, + [AC_TRY_RUN([ + main() + { +#ifdef POSIX_PGRP +# define getpgID() getpgrp() +#else +# define getpgID() getpgrp(0) +# define setpgid(x,y) setpgrp(x,y) +#endif + int pid1, pid2, fds[2]; + int status; + char ok; + switch (pid1 = fork()) { + case -1: + exit(1); + case 0: + setpgid(0, getpid()); + exit(0); + } + setpgid(pid1, pid1); + sleep(2); /* let first child die */ + if (pipe(fds) < 0) + exit(2); + switch (pid2 = fork()) { + case -1: + exit(3); + case 0: + setpgid(0, pid1); + ok = getpgID() == pid1; + write(fds[1], &ok, 1); + exit(0); + } + setpgid(pid2, pid1); + close(fds[1]); + if (read(fds[0], &ok, 1) != 1) + exit(4); + wait(&status); + wait(&status); + exit(ok ? 0 : 5); + } + ], ksh_cv_need_pgrp_sync=no, ksh_cv_need_pgrp_sync=yes, + AC_MSG_WARN(cannot test if pgrp synchronization needed when cross compiling - assuming it is) + ksh_cv_need_pgrp_sync=yes)]) + if test $ksh_cv_need_pgrp_sync = yes; then + AC_DEFINE(NEED_PGRP_SYNC) + fi + fi + ])dnl +dnl +dnl +dnl +dnl Check to see if opendir will open non-directories (not a nice thing) +AC_DEFUN(KSH_OPENDIR_CHECK, + [AC_CACHE_CHECK(if opendir() fails to open non-directories, ksh_cv_opendir_ok, + [AC_TRY_RUN([ +#include +#include +#ifdef HAVE_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ +#if defined(HAVE_DIRENT_H) +# include +#else +# define dirent direct +# ifdef SYSNDIR +# include +# endif /* SYSNDIR */ +# ifdef SYSDIR +# include +# endif /* SYSDIR */ +# ifdef NDIR +# include +# endif /* NDIR */ +#endif /* DIRENT */ + main() + { + int i, ret = 0; + FILE *fp; + char *fname = "conftestod", buf[256]; + for (i = 0; i < sizeof(buf); i++) /* memset(buf, 0, sizeof(buf)) */ + buf[i] = 0; + unlink(fname); /* paranoia */ + i = ((fp = fopen(fname, "w")) == (FILE *) 0 && (ret = 1)) + || (fwrite(buf, sizeof(buf), 1, fp) != 1 && (ret = 2)) + || (fclose(fp) == EOF && (ret = 3)) + || (opendir(fname) && (ret = 4)) + || (opendir("/dev/null") && (ret = 5)); + unlink(fname); + exit(ret); + } + ], ksh_cv_opendir_ok=yes, ksh_cv_opendir_ok=no, + AC_MSG_WARN(cannot test if opendir opens non-directories when cross compiling - assuming it does) + ksh_cv_opendir_ok=no)]) + if test $ksh_cv_opendir_ok = no; then + AC_DEFINE(OPENDIR_DOES_NONDIR) + fi + ])dnl +dnl +dnl +dnl +dnl Like AC_HAVE_HEADER(unistd.h) but only defines HAVE_UNISTD_H if +dnl the header file is sane (MIPS RISC/os 5.0 (and later?) has a unistd.h +dnl in the bsd43 environ that is incorrect - it defines POSIX_VERSION even +dnl though its non-posix). +AC_DEFUN(KSH_UNISTD_H, + [AC_CACHE_CHECK(for sane unistd.h, ksh_cv_header_unistd, + [AC_TRY_COMPILE([ +#include +#if defined(_POSIX_VERSION) +# include +# include /* _POSIX_VERSION => HAVE_DIRENT_H test not needed */ +#endif + ], , ksh_cv_header_unistd=yes, ksh_cv_header_unistd=no)]) + if test $ksh_cv_header_unistd = yes; then + AC_DEFINE(HAVE_UNISTD_H) + fi + ])dnl +dnl +dnl +dnl +dnl Several OSes need to be detected and symbols defined so the shell can +dnl deal with them. This is a bit kludgy, but... +dnl Currently tests for: +dnl AIX, ISC (Interactive systems corp), MINIX, OS2 using EMX library, +dnl SCO (santa cruz operation), NEXT +dnl DO NOT USE with AC_AIX, AC_MINIX or AC_ISC_POSIX tests as these are +dnl incorperated in this test. +AC_DEFUN(KSH_OS_TYPE, + [AC_BEFORE([$0], [AC_TRY_COMPILE])dnl + AC_BEFORE([$0], [AC_TRY_LINK])dnl + AC_BEFORE([$0], [AC_TRY_RUN])dnl + AC_CACHE_CHECK(if this is a problematic os, ksh_cv_os_type, + [ ksh_cv_os_type=no + # Some tests below add -C to CPPFLAGS + saveCPPFLAGS="$CPPFLAGS" + for i in AIX ISC MINIX SCO OS2_EMX TITANOS NEXT HPUX; do + case $i in #(( + AIX) + AC_EGREP_CPP(yes, + [ +#ifdef _AIX +yes +#endif + ], ksh_cv_os_type=$i) + ;; #( + ISC) + # Both native ISC cpp and gcc understand this (leave comments in) + CPPFLAGS="$CPPFLAGS -C" + #XXX grep part won't work if cross-compiling... + AC_EGREP_CPP(INTERACTIVE Systems Corporation, + [#include ], + [if grep _POSIX_VERSION /usr/include/sys/unistd.h > /dev/null 2>&1; then + ksh_cv_os_type="$i-posix" + else + ksh_cv_os_type=$i + fi])dnl + CPPFLAGS="$saveCPPFLAGS" + ;; #( + MINIX) + AC_CHECK_HEADER(minix/config.h, ksh_cv_os_type=$i)dnl + ;; #( + SCO) + # Both native SCO cpp and gcc understand this (leave comments in) + CPPFLAGS="$CPPFLAGS -C" + AC_EGREP_CPP(The Santa Cruz Operation, + [#include ], ksh_cv_os_type=$i)dnl + CPPFLAGS="$saveCPPFLAGS" + ;; #( + OS2_EMX) + AC_EGREP_CPP(yes, + [ +#ifdef __EMX__ +yes +#endif + ], ksh_cv_os_type=$i)dnl + ;; #( + TITANOS) + AC_EGREP_CPP(YesTitan, + [ +#if defined(titan) || defined(_titan) || defined(__titan) +YesTitan +#endif + ], ksh_cv_os_type=$i)dnl + ;; #( + NEXT) + # + # NeXT 3.2 (other versions?) - cc -E doesn't work and /lib/cpp + # doesn't define things that need defining, so tests that rely + # on $CPP will break. + # + # Hmmm - can't safely use CPP to test for NeXT defines, so have + # to use a program that won't compile on a NeXT and one that will + # only compile on a NeXT... + AC_TRY_COMPILE([], [ + #if defined(__NeXT) || defined(NeXT) + this is a NeXT box and the compile should fail + #endif + ], , AC_TRY_COMPILE([], [ + #if !defined(__NeXT) && !defined(NeXT) + this is NOT a NeXT box and the compile should fail + #endif + ], ksh_cv_os_type=$i))dnl + ;; #( + HPUX) + AC_EGREP_CPP(yes, + [ +#ifdef __hpux +yes +#endif + ], ksh_cv_os_type=$i) + ;; #( + esac #)) + test $ksh_cv_os_type != no && break + done + ]) + case $ksh_cv_os_type in #(( + AIX) + AC_DEFINE(_ALL_SOURCE)dnl + ;; #( + ISC) + AC_DEFINE(OS_ISC)dnl + ;; #( + ISC-posix) + AC_DEFINE(OS_ISC)dnl + AC_DEFINE(_POSIX_SOURCE)dnl + if test "$GCC" = yes; then + CC="$CC -posix" + else + CC="$CC -Xp" + fi + ;; #( + MINIX) + AC_DEFINE(_POSIX_SOURCE)dnl + AC_DEFINE(_POSIX_1_SOURCE, 2)dnl + AC_DEFINE(_MINIX)dnl + ;; #( + SCO) + AC_DEFINE(OS_SCO)dnl + ;; #( + OS2_EMX) + # XXX change this to OS_OS2 or OS_OS2_EMX? + AC_DEFINE(OS2)dnl + ac_exe_suffix=.exe + ;; #( + TITANOS) + # Need to use cc -43 to get a shell with job control + case "$CC" in #(( + *-43*) # Already have -43 option? + ;; #( + */cc|*/cc' '|*/cc' '|cc|cc' '|cc' ') # Using stock compiler? + CC="$CC -43" + ;; #( + esac #)) + # + # Force dirent check to find the right thing. There is a dirent.h + # (and a sys/dirent.h) file which compiles, but generates garbage... + # + ac_cv_header_dirent_dirent_h=no + ac_cv_header_dirent_sys_ndir_h=no + ac_cv_header_dirent_sys_dir_h=yes + ;; #( + NEXT) + # + # NeXT 3.2 (other versions?) - cc -E doesn't work and /lib/cpp + # doesn't define things that need defining, so tests that rely + # on $CPP will break. + # + AC_EGREP_CPP([Bad NeXT], [#include + #if !defined(SIGINT) || !defined(SIGQUIT) + Bad NeXT + #endif + ], AC_MSG_ERROR([ +There is a problem on NeXT boxes resulting in a bad siglist.out file being +generated (which breaks the trap and kill commands) and probably resulting +in many configuration tests not working correctly. + +You appear to have this problem - see the comments on NeXT in the pdksh +README file for work arounds.]))dnl + ;; #( + HPUX) + # + # In some versions of hpux (eg, 10.2), getwd & getcwd will dump core + # if directory is not readble. + # + # name is used in test program + AC_CACHE_CHECK(for bug in getwd, ksh_cv_hpux_getwd_bug, + [ tmpdir=conftest.dir + if mkdir $tmpdir ; then + AC_TRY_RUN([ + int + main() + { + char buf[8 * 1024]; + char *dirname = "conftest.dir"; + int ok = 0; + if (chdir(dirname) < 0) + exit(2); + if (chmod(".", 0) < 0) + exit(3); + /* Test won't work if run as root - so don't be root */ + if (getuid() == 0 || geteuid() == 0) + setresuid(1, 1, 1); /* hpux has this */ +#ifdef HAVE_GETWD /* silly since HAVE_* tests haven't been done yet */ + { + extern char *getwd(); + ok = getwd(buf) == 0; + } +#else + { + extern char *getcwd(); + ok = getcwd(buf, sizeof(buf)) == 0; + } +#endif + exit(ok ? 0 : 10); + return ok ? 0 : 10; + }], + ksh_cv_hpux_getwd_bug=no, ksh_cv_hpux_getwd_bug=yes, + AC_MSG_WARN(assuming getwd broken); ksh_cv_hpux_getwd_bug=yes) + test -d $tmpdir && rmdir $tmpdir + else + AC_MSG_ERROR(could not make temp directory for test); ksh_cv_hpux_getwd_bug=yes + fi]) + if test $ksh_cv_hpux_getwd_bug = yes; then + AC_DEFINE(HPUX_GETWD_BUG) + fi + ;; #( + esac #)) + ])dnl +dnl +dnl +dnl +dnl Some systems (eg, SunOS 4.0.3) have and but don't +dnl have the related functions/defines (eg, tcsetattr(), TCSADRAIN, etc.) +dnl or the functions don't work well with tty process groups. Sun's bad +dnl termios can be detected by the lack of tcsetattr(), but its bad termio +dnl is harder to detect - so check for (sane) termios first, then check for +dnl BSD, then termio. +AC_DEFUN(KSH_TERM_CHECK, + [AC_CACHE_CHECK(terminal interface, ksh_cv_term_check, + [AC_TRY_LINK([#include ], [ + struct termios t; +#if defined(ultrix) || defined(__ultrix__) + Termios in ultrix 4.2 botches type-ahead when going from cooked to + cbreak mode. The BSD tty interface works fine though, so use it + (would be good to know if alter versions of ultrix work). +#endif /* ultrix */ + tcgetattr(0, &t); tcsetattr(0, TCSADRAIN, &t); + ], ksh_cv_term_check=termios, + [AC_TRY_LINK([#include ], [ + struct sgttyb sb; ioctl(0, TIOCGETP, &sb); +#ifdef TIOCGATC + { struct ttychars lc; ioctl(0, TIOCGATC, &lc); } +#else /* TIOCGATC */ + { struct tchars tc; ioctl(0, TIOCGETC, &tc); } +# ifdef TIOCGLTC + { struct ltchars ltc; ioctl(0, TIOCGLTC, <c); } +# endif /* TIOCGLTC */ +#endif /* TIOCGATC */ + ], ksh_cv_term_check=bsd, + [AC_CHECK_HEADER(termio.h, ksh_cv_term_check=termio, + ksh_cv_term_check=sgtty)])])]) + if test $ksh_cv_term_check = termios; then + AC_DEFINE(HAVE_TERMIOS_H) +dnl Don't know of a system on which this fails... +dnl AC_CACHE_CHECK(sys/ioctl.h can be included with termios.h, +dnl ksh_cv_sys_ioctl_with_termios, +dnl [AC_TRY_COMPILE([#include +dnl #include ], , ksh_cv_sys_ioctl_with_termios=yes, +dnl ksh_cv_sys_ioctl_with_termios=no)]) +dnl if test $ksh_cv_sys_ioctl_with_termios = yes; then +dnl AC_DEFINE(SYS_IOCTL_WITH_TERMIOS) +dnl fi + elif test $ksh_cv_term_check = termio; then + AC_DEFINE(HAVE_TERMIO_H) +dnl Don't know of a system on which this fails... +dnl AC_CACHE_CHECK(sys/ioctl.h can be included with termio.h, +dnl ksh_cv_sys_ioctl_with_termio, +dnl [AC_TRY_COMPILE([#include +dnl #include ], , ksh_cv_sys_ioctl_with_termio=yes, +dnl ksh_cv_sys_ioctl_with_termio=no)]) +dnl if test $ksh_cv_sys_ioctl_with_termio = yes; then +dnl AC_DEFINE(SYS_IOCTL_WITH_TERMIO) +dnl fi + fi + ])dnl +dnl +dnl +dnl +dnl Check if lstat() is available - special test needed 'cause lstat only +dnl becomes visable if is included (linux 1.3.x)... +AC_DEFUN(KSH_FUNC_LSTAT, +[AC_CACHE_CHECK(for lstat, ksh_cv_func_lstat, +[AC_TRY_LINK([ +#include +#include + ], [ + struct stat statb; + lstat("/", &statb); + ], + ksh_cv_func_lstat=yes, ksh_cv_func_lstat=no)]) +if test $ksh_cv_func_lstat = yes; then + AC_DEFINE(HAVE_LSTAT) +fi +]) +dnl +dnl +dnl +dnl Modified test from autoconf's acspecific.m4: MMAP test needs to check +dnl for/use the MAP_FILE flag. (Needed for older NetBSD systems). +undefine([AC_FUNC_MMAP])dnl +AC_DEFUN(AC_FUNC_MMAP, +[AC_CHECK_FUNCS(valloc getpagesize) +AC_CACHE_CHECK(for working mmap, ac_cv_func_mmap, +[AC_TRY_RUN([ +/* Thanks to Mike Haertel and Jim Avera for this test. */ +#include +#include +#include + +#ifndef HAVE_GETPAGESIZE +# include +# ifdef EXEC_PAGESIZE +# define getpagesize() EXEC_PAGESIZE +# else +# ifdef NBPG +# define getpagesize() NBPG * CLSIZE +# ifndef CLSIZE +# define CLSIZE 1 +# endif +# else +# ifdef NBPC +# define getpagesize() NBPC +# else +# define getpagesize() PAGESIZE /* SVR4 */ +# endif +# endif +# endif +#endif + +#ifndef HAVE_VALLOC +# define valloc malloc +#endif + +#ifdef __cplusplus +extern "C" { void *valloc(unsigned), *malloc(unsigned); } +#else +char *valloc(), *malloc(); +#endif + +#ifndef MAP_FILE +# define MAP_FILE 0 +#endif /* MAP_FILE */ + +int +main() +{ + char *buf1, *buf2, *buf3; + int i = getpagesize(), j; + int i2 = i * 2; + int fd; + + buf1 = (char *)valloc(i2); + buf2 = (char *)valloc(i); + buf3 = (char *)malloc(i2); + for (j = 0; j < i2; ++j) + *(buf1 + j) = rand(); + fd = open("conftestmmap", O_CREAT | O_RDWR, 0666); + write(fd, buf1, i2); + mmap(buf2, i, PROT_READ | PROT_WRITE, MAP_FILE | MAP_FIXED | MAP_PRIVATE, fd, 0); + for (j = 0; j < i; ++j) + if (*(buf1 + j) != *(buf2 + j)) + exit(1); + lseek(fd, (long)i, 0); + read(fd, buf2, i); /* read into mapped memory -- file should not change */ + /* (it does in i386 SVR4.0 - Jim Avera, jima@netcom.com) */ + lseek(fd, (long)0, 0); + read(fd, buf3, i2); + for (j = 0; j < i2; ++j) + if (*(buf1 + j) != *(buf3 + j)) + exit(1); + exit(0); +} +], ac_cv_func_mmap=yes, ac_cv_func_mmap=no, ac_cv_func_mmap=no)]) +if test $ac_cv_func_mmap = yes; then + AC_DEFINE(HAVE_MMAP) +fi +]) +dnl +dnl +dnl +dnl Modified AC_LANG_C, AC_LANG_CPLUSPLUS, AC_TRY_RUN to handle executable +dnl extensions. +undefine([AC_LANG_C])dnl +undefine([AC_LANG_CPLUXPLUS])dnl +undefine([AC_TRY_RUN])dnl +dnl AC_LANG_C() +AC_DEFUN(AC_LANG_C, +[define([AC_LANG], [C])dnl +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='echo $CPP $CPPFLAGS 1>&AC_FD_CC; +$CPP $CPPFLAGS' +ac_compile='echo ${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&AC_FD_CC; +${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&AC_FD_CC 2>&AC_FD_CC' +ac_link='echo ${CC-cc} -o conftest$ac_exe_suffix $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&AC_FD_CC; +${CC-cc} -o conftest$ac_exe_suffix $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&AC_FD_CC 2>&AC_FD_CC' +]) + +dnl AC_LANG_CPLUSPLUS() +AC_DEFUN(AC_LANG_CPLUSPLUS, +[define([AC_LANG], [CPLUSPLUS])dnl +ac_ext=C +# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='echo $CXXCPP $CPPFLAGS 1>&AC_FD_CC; +$CXXCPP $CPPFLAGS' +ac_compile='echo ${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&AC_FD_CC; +${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&AC_FD_CC 2>&AC_FD_CC' +ac_link='echo ${CXX-g++} -o conftest$ac_exe_suffix $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&AC_FD_CC; +${CXX-g++} -o conftest$ac_exe_suffix $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&AC_FD_CC 2>&AC_FD_CC' +]) +dnl AC_TRY_RUN(PROGRAM, [ACTION-IF-TRUE [, ACTION-IF-FALSE +dnl [, ACTION-IF-CROSS-COMPILING]]]) +AC_DEFUN(AC_TRY_RUN, +[AC_REQUIRE([AC_PROG_CC])dnl +if test "$cross_compiling" = yes; then + ifelse([$4], , + [errprint(__file__:__line__: warning: [AC_TRY_RUN] called without default to allow cross compiling +)dnl + AC_MSG_ERROR(can not run test program while cross compiling)], + [$4]) +else +cat > conftest.$ac_ext </dev/null; then + ifelse([$2], , :, [$2]) +ifelse([$3], , , [else + $3 +])dnl +fi +fi +rm -fr conftest*]) +dnl +dnl +dnl Like AC_HEADER_SYS_WAIT, only HAVE_SYS_WAIT_H if sys/wait.h exists and +dnl defines POSIX_SYS_WAIT if it is posix compatable. This way things +dnl like WNOHANG, WUNTRACED can still be used. +AC_DEFUN(KSH_HEADER_SYS_WAIT, +[AC_CACHE_CHECK([for sys/wait.h that is POSIX.1 compatible], ksh_cv_header_sys_wait_h, +[AC_TRY_COMPILE([#include +#include +#ifndef WEXITSTATUS +#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) +#endif +#ifndef WIFEXITED +#define WIFEXITED(stat_val) (((stat_val) & 255) == 0) +#endif], [int s; +wait (&s); +s = WIFEXITED (s) ? WEXITSTATUS (s) : 1;], +ksh_cv_header_sys_wait_h=yes, ksh_cv_header_sys_wait_h=no)]) +if test $ksh_cv_header_sys_wait_h = yes; then + AC_DEFINE(POSIX_SYS_WAIT)dnl + AC_DEFINE(HAVE_SYS_WAIT_H)dnl +else + AC_CHECK_HEADERS(sys/wait.h)dnl +fi +]) +dnl +dnl +dnl Modified test from autoconf's acspecific.m4(AC_HEADER_STAT) test: need +dnl to check if S_ISSOCK == S_ISFIFO (FreeBSD). +undefine([AC_HEADER_STAT])dnl +AC_DEFUN(AC_HEADER_STAT, +[AC_CACHE_CHECK(whether stat file-mode macros are broken, + ac_cv_header_stat_broken, +[AC_EGREP_CPP([You lose], [#include +#include + +#if defined(S_ISBLK) && defined(S_IFDIR) +# if S_ISBLK (S_IFDIR) +You lose. +# endif +#endif + +#if defined(S_ISBLK) && defined(S_IFCHR) +# if S_ISBLK (S_IFCHR) +You lose. +# endif +#endif + +#if defined(S_ISLNK) && defined(S_IFREG) +# if S_ISLNK (S_IFREG) +You lose. +# endif +#endif + +#if defined(S_ISSOCK) && defined(S_IFREG) +# if S_ISSOCK (S_IFREG) +You lose. +# endif +#endif + +#if defined(S_ISSOCK) && defined(S_IFIFO) +# if S_ISSOCK (S_IFIFO) +You lose. +# endif +#endif +], ac_cv_header_stat_broken=yes, ac_cv_header_stat_broken=no)]) +if test $ac_cv_header_stat_broken = yes; then + AC_DEFINE(STAT_MACROS_BROKEN) +fi +]) +dnl +dnl +dnl Need to change the "accepts -g" test - some broken systems +dnl allow "cc -c -g ..." but fail on the link (missing -lg). +dnl LaserMoon's linux/FT is such a broken system... +undefine([AC_PROG_CC])dnl +AC_DEFUN(AC_PROG_CC, +[AC_BEFORE([$0], [AC_PROG_CPP])dnl +AC_CHECK_PROG(CC, gcc, gcc, cc) + +AC_CACHE_CHECK(whether we are using GNU C, ac_cv_prog_gcc, +[dnl The semicolon is to pacify NeXT's syntax-checking cpp. +cat > conftest.c <&AC_FD_CC | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gcc=yes +else + ac_cv_prog_gcc=no +fi]) +if test $ac_cv_prog_gcc = yes; then + GCC=yes + if test "${CFLAGS+set}" != set; then + AC_CACHE_CHECK(whether ${CC-cc} accepts -g, ac_cv_prog_gcc_g, +[echo 'int main(){ return 0; }' > conftest.c +if test -z "`${CC-cc} -g conftest.c 2>&1`"; then + ac_cv_prog_gcc_g=yes +else + ac_cv_prog_gcc_g=no +fi +rm -f conftest* +]) + if test $ac_cv_prog_gcc_g = yes; then + CFLAGS="-g -O" + else + CFLAGS="-O" + fi + fi +else + GCC= + test "${CFLAGS+set}" = set || CFLAGS="-g" +fi +]) +dnl +dnl +dnl Need to change to check for ndir +dnl +undefine([AC_HEADER_DIRENT])dnl +AC_DEFUN(AC_HEADER_DIRENT, +[ac_header_dirent=no +AC_CHECK_HEADERS_DIRENT(dirent.h sys/ndir.h sys/dir.h ndir.h, + [ac_header_dirent=$ac_hdr; break]) +# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. +if test $ac_header_dirent = dirent.h; then +AC_CHECK_LIB(dir, opendir, LIBS="$LIBS -ldir", AC_CHECK_LIB(ndir, opendir, LIBS="$LIBS -lndir")) +else +AC_CHECK_LIB(x, opendir, LIBS="$LIBS -lx") +fi +]) diff --git a/check-fd.c b/check-fd.c new file mode 100644 index 0000000..5055e62 --- /dev/null +++ b/check-fd.c @@ -0,0 +1,89 @@ +/* A simple program to check which file descriptors are open and + * print some info about them. + */ + +#include "config.h" +#include +#include +#ifdef HAVE_STDLIB_H +# include +#endif /* HAVE_STDLIB_H */ +#ifdef HAVE_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ +#ifdef HAVE_FCNTL_H +# include +#else /* HAVE_FCNTL_H */ +# include +#endif /* HAVE_FCNTL_H */ +#include "ksh_stat.h" + +int usage(); + +char *progname = "check-fd"; + +#define MAXFD 256 /* a somewhat arbitrary number */ + +int +main(argc, argv) + int argc; + char **argv; +{ + extern int optind; + + int opt; + int do_close = 0; + struct stat statb; + int i; + + if (argc > 0 && argv[0] && *argv[0]) + progname = argv[0]; + + while ((opt = getopt(argc, argv, "c")) != EOF) { + switch (opt) { + case 'c': + do_close = 1; + break; + + default: + usage(1); + } + } + + if (optind != argc) { + fprintf(stderr, "%s: too many arguments\n", progname); + usage(0); + } + + if (do_close) { + for (i = 0; i < MAXFD; i++) + if (i == 1) + printf("(can't check 1)\n"); + else if (close(i) >= 0) + printf("%d was open\n", i); + } else { + for (i = 0; i < MAXFD; i++) + if (fstat(i, &statb) == 0) + printf( + "%d is open (dev/inode %hd/%ld, flags 0x%x)\n", + i, statb.st_dev, statb.st_ino, + fcntl(i, F_GETFL, 0)); + } + + return 0; +} + +int +usage(verbose) + int verbose; +{ + fprintf(stderr, "Usage: %s [-?c]\n", progname); + if (verbose) + fprintf(stderr, "\ + -c use close(2) instead of fstat(2) to check for open fds\n\ + (prints dev, inode and fcntl(F_GETFL) flags)\n\ +"); + + exit(1); + return 0; +} diff --git a/check-pgrp.c b/check-pgrp.c new file mode 100644 index 0000000..f4d8d09 --- /dev/null +++ b/check-pgrp.c @@ -0,0 +1,101 @@ +/* A simple program to print information about process groups */ + +#include "config.h" +#include +#include +#ifdef HAVE_STDLIB_H +# include +#endif /* HAVE_STDLIB_H */ +#ifdef HAVE_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ +#ifdef HAVE_FCNTL_H +# include +#else /* HAVE_FCNTL_H */ +# include +#endif /* HAVE_FCNTL_H */ + +#ifdef BSD_PGRP +# include +int +tcgetpgrp(fd) + int fd; +{ + int r, grp; + + if ((r = ioctl(fd, TIOCGPGRP, &grp)) < 0) + return r; + return grp; +} +# define getPGRP() getpgrp(0) +#else /* BSD_PGRP */ +# define getPGRP() getpgrp() +#endif /* BSD_PGRP */ + +int usage(); + +char *progname = "check-pgrp"; + +int +main(argc, argv) + int argc; + char **argv; +{ + extern int optind; + extern char *optarg; + + int opt; + int ttyfd = 0; + int my_pgrp, my_pid, my_ppid, tty_pgrp; + char *tty_name; + char *e; + + if (argc > 0 && argv[0] && *argv[0]) + progname = argv[0]; + + while ((opt = getopt(argc, argv, "u:")) != EOF) { + switch (opt) { + case 'u': + ttyfd = atoi(optarg); + break; + + default: + usage(1); + } + } + + if (optind != argc) { + fprintf(stderr, "%s: too many arguments\n", progname); + usage(0); + } + + my_pid = getpid(); + my_ppid = getppid(); + my_pgrp = getPGRP(); + tty_pgrp = tcgetpgrp(ttyfd); + tty_name = ttyname(ttyfd); + + printf("in %s pgrp\ntty %s (%s)\npid %d, ppid %d, pgrp %d, tty_pgrp %d\n", + my_pgrp == my_pid ? "my own" + : (my_pgrp == my_ppid ? "parent's" : "unknown"), + tty_name ? tty_name : "(none)", + tty_pgrp == my_pgrp ? "mine" + : (tty_pgrp == my_ppid ? "parent's" : "unknown"), + my_pid, my_ppid, my_pgrp, tty_pgrp); + + return 0; +} + +int +usage(verbose) + int verbose; +{ + fprintf(stderr, "Usage: %s [-?] [-u fd]\n", progname); + if (verbose) + fprintf(stderr, "\ + -u fd use fd as tty fd (default is 0)\n\ +"); + + exit(1); + return 0; +} diff --git a/check-sigs.c b/check-sigs.c new file mode 100644 index 0000000..91f288b --- /dev/null +++ b/check-sigs.c @@ -0,0 +1,255 @@ +/* A simple program to print information about signal handlers */ + +#include "config.h" +#include +#include +#include +#include +#ifdef HAVE_STRING_H +# include +#else +# include +# define strchr index +# define strrchr rindex +#endif /* HAVE_STRING_H */ +#ifdef HAVE_STDLIB_H +# include +#endif /* HAVE_STDLIB_H */ +#ifdef HAVE_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ + +#ifndef SIG_ERR +# define SIG_ERR ((RETSIGTYPE (*)()) -1) +#endif /* SIG_ERR */ + +/* must be similar to struct Trap in sh.h */ +struct signal_info { + int signal; + char *name; + char *mess; +}; +struct signal_info siginfo[] = { + { 0, "0", "Signal 0" }, +#include "siglist.out" + { 0, (char *) 0, (char *)0 }, +}; + +int usage(); +#if 0 +RETSIGTYPE sig_catcher(); +#endif /* 0 */ +char *signal_name(); +#ifndef HAVE_STRERROR +char *strerror(int); +#endif /* !HAVE_STRERROR */ + +char *progname = "check-sigs"; +int caught_sigs; + +int +main(argc, argv) + int argc; + char **argv; +{ + extern int optind; + extern char *optarg; + extern int errno; + + int opt; + int i; + int eno; + int report_all = 0; + RETSIGTYPE (*f)(); + char *ofile = (char *) 0; + char *s; + int wait_forever = 0; + + if (argc > 0 && argv[0] && *argv[0]) + progname = argv[0]; + + while ((opt = getopt(argc, argv, "ao:w")) != EOF) { + switch (opt) { + case 'a': + report_all = 1; + break; + + case 'o': + ofile = optarg; + break; + + case 'w': + wait_forever = 1; + break; + + default: + usage(1); + } + } + + if (argc != optind) + usage(0); + + if (ofile && freopen(ofile, "w", stdout) == (FILE *) 0) { + fprintf(stderr, "%s: Couldn't open output file `%s' - %s\n", + progname, ofile, strerror(errno)); + exit(1); + } + + if (!wait_forever) { + char *blocked = ""; +#ifdef POSIX_SIGNALS + sigset_t mask; + + sigprocmask(SIG_BLOCK, (sigset_t *) 0, &mask); +#endif /* POSIX_SIGNALS */ +#ifdef BSD42_SIGNALS + int mask; + + mask = sigblock(0); +#endif /* BSD42_SIGNALS */ + for (i = 1; i < NSIG; i++) { + f = signal(i, SIG_DFL); + eno = errno; +#ifdef BSD42_SIGNALS + blocked = (mask & sigmask(i)) ? "blocked" : ""; +#endif /* BSD42_SIGNALS */ +#ifdef POSIX_SIGNALS + blocked = sigismember(&mask, i) ? "blocked" : ""; +#endif /* POSIX_SIGNALS */ + if (f == SIG_DFL && !report_all && !*blocked) + continue; + printf("%3d: %7s %30s: ", + i, blocked, (s = signal_name(i)) ? s : ""); + if (f == SIG_IGN) + printf("ignored\n"); + else if (f == SIG_ERR) + printf("error - %s\n", strerror(eno)); + else if (f != SIG_DFL) + printf("caught - function address %lx\n", + (long) f); + else if (report_all) + printf("default\n"); + } + } + +#if 0 /* code assumes BSD signals - not worth posixizing */ + if (wait_forever) { + printf("pid is %d\n", getpid()); + sigsetmask(-1L); + for (i = 0; i < NSIG; i++) + (void) signal(i, sig_catcher); + while (1) { + sigpause(0L); + for (i = 1; i < NSIG; i++) + if (caught_sigs & sigmask(i)) + printf("received signal %d - %s\n", + i, + (s = signal_name(i)) ? s + : ""); + caught_sigs = 0L; + } + } +#endif + + return 0; +} + +int +usage(verbose) + int verbose; +{ + fprintf(stderr, "Usage: %s [-?aw] [-o file]\n", progname); + if (verbose) + fprintf(stderr, "\ + -a report on all signals - instead of just non-default signals\n\ + -o f redirect standard output to file f\n\ + -w wait forever, reporting all signals sent\n\ +"); + + exit(1); + return 0; +} + +#if 0 +RETSIGTYPE +sig_catcher(sig) + int sig; +{ + caught_sigs |= sigmask(sig); + return RETSIGVAL; +} +#endif /* 0 */ + + + +char * +signal_name(sig) + int sig; +{ + static char buf[1024]; + +#ifdef HAVE_SYS_SIGLIST +# ifndef SYS_SIGLIST_DECLARED + extern char *sys_siglist[]; +# endif + /* Use system description, if available... */ + if (sys_siglist[sig] && sys_siglist[sig][0]) + return sys_siglist[sig]; +#endif /* HAVE_SYS_SIGLIST */ + + + if (sig > 0 && sig < sizeof(siginfo) / sizeof(siginfo[0]) - 1) { + sprintf(buf, "SIG%s (%s)", + siginfo[sig].name, siginfo[sig].mess); + return buf; + } + + return (char *) 0; +} + +#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) + sprintf(p = 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: + sprintf(buf, "Unknown system error %d", err); + return buf; + } +# endif /* HAVE_SYS_ERRLIST */ +} +#endif /* !HAVE_STRERROR */ diff --git a/config.h.in b/config.h.in new file mode 100644 index 0000000..bf16ac9 --- /dev/null +++ b/config.h.in @@ -0,0 +1,360 @@ +/* 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 doesn't define. */ +#undef gid_t + +/* Define if you have a working `mmap' system call. */ +#undef HAVE_MMAP + +/* Define if your struct stat has st_rdev. */ +#undef HAVE_ST_RDEV + +/* Define if you have that is POSIX.1 compatible. */ +#undef HAVE_SYS_WAIT_H + +/* Define if you have . */ +#undef HAVE_UNISTD_H + +/* Define if on MINIX. */ +#undef _MINIX + +/* Define to `int' if doesn't define. */ +#undef mode_t + +/* Define to `long' if doesn't define. */ +#undef off_t + +/* Define to `int' if 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). */ +#undef RETSIGTYPE + +/* Define if the `S_IS*' macros in do not work properly. */ +#undef STAT_MACROS_BROKEN + +/* Define if `sys_siglist' is declared by . */ +#undef SYS_SIGLIST_DECLARED + +/* Define if you can safely include both and . */ +#undef TIME_WITH_SYS_TIME + +/* Define to `int' if 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 ). */ +#undef RETSIGVAL + +/* Define if you have posix signal routines (sigaction(), et. al.) */ +#undef POSIX_SIGNALS + +/* 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 */ +#undef POSIX_PGRP + +/* 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 */ +#undef HAVE_PROTOTYPES + +/* Define if C compiler groks __attribute__((...)) (const, noreturn, format) */ +#undef HAVE_GCC_FUNC_ATTR + +/* Define to 32-bit signed integer type if 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 */ +#undef TIME_DECLARED + +/* Define to `unsigned' if doesn't define */ +#undef sigset_t + +/* Define if sys_errlist[] and sys_nerr are in the C library */ +#undef HAVE_SYS_ERRLIST + +/* Define if sys_errlist[] and sys_nerr are defined in */ +#undef SYS_ERRLIST_DECLARED + +/* Define if sys_siglist[] is in the C library */ +#undef HAVE_SYS_SIGLIST + +/* Define if you have a sane header file */ +#undef HAVE_TERMIOS_H + +/* Define if you have a memset() function in your C library */ +#undef HAVE_MEMSET + +/* Define if you have a memmove() function in your C library */ +#undef HAVE_MEMMOVE + +/* 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 */ +#undef HAVE_LSTAT + +/* Define if you have a sane 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 */ +#undef POSIX_SYS_WAIT + +/* Define if your OS maps references to /dev/fd/n to file descriptor n */ +#undef HAVE_DEV_FD + +/* Define if your C library's getwd/getcwd function dumps core in unreadable + * directories. */ +#undef HPUX_GETWD_BUG + +/* Default PATH (see comments in configure.in for more details) */ +#undef DEFAULT_PATH + +/* Include ksh features? (see comments in configure.in for more details) */ +#undef KSH + +/* Include emacs editing? (see comments in configure.in for more details) */ +#undef EMACS + +/* Include vi editing? (see comments in configure.in for more details) */ +#undef VI + +/* Include job control? (see comments in configure.in for more details) */ +#undef JOBS + +/* Include brace-expansion? (see comments in configure.in for more details) */ +#undef BRACE_EXPAND + +/* Include any history? (see comments in configure.in for more details) */ +#undef HISTORY + +/* 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. */ +#undef SIZEOF_INT + +/* The number of bytes in a long. */ +#undef SIZEOF_LONG + +/* Define if you have the _setjmp function. */ +#undef HAVE__SETJMP + +/* Define if you have the confstr function. */ +#undef HAVE_CONFSTR + +/* Define if you have the dup2 function. */ +#undef HAVE_DUP2 + +/* Define if you have the flock function. */ +#undef HAVE_FLOCK + +/* Define if you have the getcwd function. */ +#undef HAVE_GETCWD + +/* Define if you have the getgroups function. */ +#undef HAVE_GETGROUPS + +/* Define if you have the getpagesize function. */ +#undef HAVE_GETPAGESIZE + +/* Define if you have the getrusage function. */ +#undef HAVE_GETRUSAGE + +/* Define if you have the getwd function. */ +#undef HAVE_GETWD + +/* Define if you have the killpg function. */ +#undef HAVE_KILLPG + +/* Define if you have the nice function. */ +#undef HAVE_NICE + +/* Define if you have the setrlimit function. */ +#undef HAVE_SETRLIMIT + +/* Define if you have the sigsetjmp function. */ +#undef HAVE_SIGSETJMP + +/* Define if you have the strcasecmp function. */ +#undef HAVE_STRCASECMP + +/* Define if you have the strerror function. */ +#undef HAVE_STRERROR + +/* Define if you have the strstr function. */ +#undef HAVE_STRSTR + +/* Define if you have the sysconf function. */ +#undef HAVE_SYSCONF + +/* Define if you have the tcsetpgrp function. */ +#undef HAVE_TCSETPGRP + +/* Define if you have the ulimit function. */ +#undef HAVE_ULIMIT + +/* Define if you have the valloc function. */ +#undef HAVE_VALLOC + +/* Define if you have the wait3 function. */ +#undef HAVE_WAIT3 + +/* Define if you have the waitpid function. */ +#undef HAVE_WAITPID + +/* Define if you have the header file. */ +#undef HAVE_DIRENT_H + +/* Define if you have the header file. */ +#undef HAVE_FCNTL_H + +/* Define if you have the header file. */ +#undef HAVE_LIMITS_H + +/* Define if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define if you have the header file. */ +#undef HAVE_NDIR_H + +/* Define if you have the header file. */ +#undef HAVE_PATHS_H + +/* Define if you have the header file. */ +#undef HAVE_STDDEF_H + +/* Define if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define if you have the header file. */ +#undef HAVE_STRING_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_DIR_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_NDIR_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_PARAM_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_RESOURCE_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_WAIT_H + +/* Define if you have the header file. */ +#undef HAVE_ULIMIT_H + +/* Define if you have the 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/configure b/configure new file mode 100644 index 0000000..ee34802 --- /dev/null +++ b/configure @@ -0,0 +1,4447 @@ +#! /bin/sh + + + + + + + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.12 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: +ac_help="$ac_help + --enable-path=PaTh (NOTE: this value isn't used if confstr() and _CS_PATH + are available, or if defines _PATH_DEFPATH) + Use PaTh if PATH isn't specified in the environment + when the shell starts. A value without . in it is + safest. + The default value is \"/bin:/usr/bin:/usr/ucb\"." +ac_help="$ac_help + --enable-shell={sh,ksh} Specify the kind of shell that is to be built (the + default is ksh). Specifiying sh compiles out: + command line editing (emacs/vi), history, + a bunch of aliases, [[ .. ]], select, let, + brace-expansion, extended globing (*(..|..), etc.), + co-processes, some special environment variables + (ie, MAIL, MAILCHECK, MAILPATH, RANDOM, SECONDS, + TMOUT)." +ac_help="$ac_help + --disable-emacs Compile out emacs command line editing (by default, + this is compiled in for ksh, compiled out for sh)." +ac_help="$ac_help + --disable-vi Compile out vi command line editing (by default, + this is compiled in for ksh, compiled out for sh)." +ac_help="$ac_help + --disable-jobs Compile out job control support. If your system + doesn't support job control, this will automatically + be compiled out." +ac_help="$ac_help + --disable-brace-expand Compile out brace expansion code (a{b,c} -> ab ac) + (by default, this is compiled in for ksh, compiled + out for sh). Brace expansion can also be disabled + at run time (see set +o braceexpand)." +ac_help="$ac_help + --enable-history={no,simple,complex} By default, simple history is used for + ksh, no history is used for sh. \`simple' means + history file is read on start-up, written when shell + exists. \`complex' means history files are updated + after each command so concurrent shells read each + other's commands. Note: \`complex' history doesn't + work well across NFS; also, it requires the mmap() + and flock() functions - if these aren't available, + \`simple' history is automatically used." +ac_help="$ac_help + --enable-posixly-correct Enable if you want POSIX behavior by default + (otherwise, posix behavior is only turned on if the + environment variable POSIXLY_CORRECT is present or by + using \"set -o posix\"; it can be turned off with + \"set +o posix\"). See the POSIX Mode section in the + man page for details on what this option affects. + NOTE: posix mode is not compatable with some bourne + sh/at&t ksh scripts." +ac_help="$ac_help + --enable-default-env=FILE Include FILE if ENV parameter is not set when + the shell starts. This can be useful when used with + rsh(1), which creates a non-login shell (ie, profile + isn't read, so there is no opertunity to set ENV). + Setting ENV to null disables the inclusion of + DEFAULT_ENV. NOTE: This is a non-standard feature + (ie, at&t ksh has no default environment)." +ac_help="$ac_help + --enable-silly [A silly option]" +ac_help="$ac_help + --enable-swtch For use with shell layers (shl(1)). This has not + been tested for some time." + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.12" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=c_ksh.c + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='echo $CPP $CPPFLAGS 1>&5; +$CPP $CPPFLAGS' +ac_compile='echo ${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5; +${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5 2>&5' +ac_link='echo ${CC-cc} -o conftest$ac_exe_suffix $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5; +${CC-cc} -o conftest$ac_exe_suffix $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5 2>&5' + +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + + + +def_path_unix="/bin:/usr/bin:/usr/ucb" +def_path_os2="c:/usr/bin;c:/os2;/os2" +# Check whether --enable-path or --disable-path was given. +if test "${enable_path+set}" = set; then + enableval="$enable_path" + : +else + enable_path=default +fi + +case $enable_path:$ksh_cv_os_type in + default:OS2_EMX) enable_path="$def_path_os2" ;; + default:*) enable_path="$def_path_unix" ;; +esac +case $enable_path in + \"*\") ;; + *) + enable_path="\"$enable_path\"" + ;; +esac +cat >> confdefs.h <> confdefs.h <<\EOF +#define KSH 1 +EOF + ;; + sh) ;; + *) + { echo "configure: error: bad --enable-shell: must be one of sh or ksh" 1>&2; exit 1; } +esac +SHELL_PROG=$enable_shell + +# Check whether --enable-emacs or --disable-emacs was given. +if test "${enable_emacs+set}" = set; then + enableval="$enable_emacs" + : +fi + +case $enable_emacs:$enable_shell in + yes:*|:ksh) enable_emacs=yes; cat >> confdefs.h <<\EOF +#define EMACS 1 +EOF + ;; + no:*|:sh) enable_emacs=no;; + *) { echo "configure: error: bad --enable-emacs argument" 1>&2; exit 1; } +esac +# Check whether --enable-vi or --disable-vi was given. +if test "${enable_vi+set}" = set; then + enableval="$enable_vi" + : +fi + +case $enable_vi:$enable_shell in + yes:*|:ksh) enable_vi=yes; cat >> confdefs.h <<\EOF +#define VI 1 +EOF + ;; + no:*|:sh) enable_vi=no;; + *) { echo "configure: error: bad --enable-vi argument" 1>&2; exit 1; } +esac +# Check whether --enable-jobs or --disable-jobs was given. +if test "${enable_jobs+set}" = set; then + enableval="$enable_jobs" + : +fi + +case $enable_jobs in + yes|'') enable_jobs=yes; cat >> confdefs.h <<\EOF +#define JOBS 1 +EOF + ;; + no) enable_jobs=no;; + *) { echo "configure: error: bad --enable-jobs argument" 1>&2; exit 1; } +esac +# Check whether --enable-brace-expand or --disable-brace-expand was given. +if test "${enable_brace_expand+set}" = set; then + enableval="$enable_brace_expand" + : +fi + +case $enable_brace_expand:$enable_shell in + yes:*|:ksh) enable_brace_expand=yes; cat >> confdefs.h <<\EOF +#define BRACE_EXPAND 1 +EOF + ;; + no:*|:sh) enable_brace_expand=no;; + *) { echo "configure: error: bad --enable-brace-expand argument" 1>&2; exit 1; } +esac +# Check whether --enable-history or --disable-history was given. +if test "${enable_history+set}" = set; then + enableval="$enable_history" + : +fi + +case $enable_history:$enable_shell in + simple:*|:ksh) enable_history=simple; ;; + complex:*) enable_history=complex; cat >> confdefs.h <<\EOF +#define COMPLEX_HISTORY 1 +EOF + ;; + no:*|:sh) + case $enable_history:$enable_vi:$enable_emacs in + no:yes:*|no:*:yes) + { echo "configure: error: can't disable history when vi or emacs is enabled" 1>&2; exit 1; } ;; + :yes:*|:*:yes) + enable_history=yes;; + *) + enable_history=no;; + esac + ;; + *) { echo "configure: error: bad --enable-history argument" 1>&2; exit 1; } +esac +test X"$enable_history" != Xno && cat >> confdefs.h <<\EOF +#define HISTORY 1 +EOF + +# Check whether --enable-posixly_correct or --disable-posixly_correct was given. +if test "${enable_posixly_correct+set}" = set; then + enableval="$enable_posixly_correct" + : +fi + +case $enable_posixly_correct:$enable_shell in + yes:*) enable_posixly_correct=yes; cat >> confdefs.h <<\EOF +#define POSIXLY_CORRECT 1 +EOF + ;; + no:*|:*) enable_posixly_correct=no;; + *) { echo "configure: error: bad --enable-posixly_correct argument" 1>&2; exit 1; } +esac +# Check whether --enable-default-env or --disable-default-env was given. +if test "${enable_default_env+set}" = set; then + enableval="$enable_default_env" + : +else + enable_default_env=no +fi + +if test X"$enable_default_env" != Xno; then + # The [a-zA-Z]:/ is for os2 types... + case $enable_default_env in + /*|[a-zA-Z]:/*) + enable_default_env="\"$enable_default_env\"" + ;; + \"/*\"|\"[a-zA-Z]:/*\") + ;; + *) + { echo "configure: error: --enable-default-env argument must be an absolute path (was $enable_default_env)" 1>&2; exit 1; } + ;; + esac + cat >> confdefs.h <> confdefs.h <<\EOF +#define SILLY 1 +EOF + ;; + no:*|:*) enable_silly=no;; + *) { echo "configure: error: bad --enable-silly argument" 1>&2; exit 1; } +esac +# Check whether --enable-swtch or --disable-swtch was given. +if test "${enable_swtch+set}" = set; then + enableval="$enable_swtch" + : +fi + +case $enable_swtch:$enable_shell in + yes:*) enable_swtch=yes; cat >> confdefs.h <<\EOF +#define SWTCH 1 +EOF + ;; + no:*|:*) enable_swtch=no;; + *) { echo "configure: error: bad --enable-swtch argument" 1>&2; exit 1; } +esac +# Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:791: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="gcc" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_CC" && ac_cv_prog_CC="cc" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + +echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 +echo "configure:819: checking whether we are using GNU C" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.c <&5 | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gcc=yes +else + ac_cv_prog_gcc=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gcc" 1>&6 +if test $ac_cv_prog_gcc = yes; then + GCC=yes + if test "${CFLAGS+set}" != set; then + echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 +echo "configure:840: checking whether ${CC-cc} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gcc_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'int main(){ return 0; }' > conftest.c +if test -z "`${CC-cc} -g conftest.c 2>&1`"; then + ac_cv_prog_gcc_g=yes +else + ac_cv_prog_gcc_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_gcc_g" 1>&6 + if test $ac_cv_prog_gcc_g = yes; then + CFLAGS="-g -O" + else + CFLAGS="-O" + fi + fi +else + GCC= + test "${CFLAGS+set}" = set || CFLAGS="-g" +fi + +echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 +echo "configure:867: checking how to run the C preprocessor" >&5 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then +if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # This must be in double quotes, not single quotes, because CPP may get + # substituted into the Makefile and "${CC-cc}" will confuse make. + CPP="${CC-cc} -E" + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:888: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -E -traditional-cpp" + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:905: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP=/lib/cpp +fi +rm -f conftest* +fi +rm -f conftest* + ac_cv_prog_CPP="$CPP" +fi + CPP="$ac_cv_prog_CPP" +else + ac_cv_prog_CPP="$CPP" +fi +echo "$ac_t""$CPP" 1>&6 + +if test $ac_cv_prog_gcc = yes; then + echo $ac_n "checking whether ${CC-cc} needs -traditional""... $ac_c" 1>&6 +echo "configure:929: checking whether ${CC-cc} needs -traditional" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gcc_traditional'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_pattern="Autoconf.*'x'" + cat > conftest.$ac_ext < +Autoconf TIOCGETP +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "$ac_pattern" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_prog_gcc_traditional=yes +else + rm -rf conftest* + ac_cv_prog_gcc_traditional=no +fi +rm -f conftest* + + + if test $ac_cv_prog_gcc_traditional = no; then + cat > conftest.$ac_ext < +Autoconf TCGETA +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "$ac_pattern" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_prog_gcc_traditional=yes +fi +rm -f conftest* + + fi +fi + +echo "$ac_t""$ac_cv_prog_gcc_traditional" 1>&6 + if test $ac_cv_prog_gcc_traditional = yes; then + CC="$CC -traditional" + fi +fi + +if test X"$GCC" = Xyes && test -f $srcdir/Warn-flags; then + CFLAGS="${CFLAGS+$CFLAGS }`cat $srcdir/Warn-flags`" +fi + +LDSTATIC=${LDSTATIC-} +test X"$LDSTATIC" != X && LDFLAGS="${LDFLAGS+$LDFLAGS }$LDSTATIC" + + echo $ac_n "checking if this is a problematic os""... $ac_c" 1>&6 +echo "configure:982: checking if this is a problematic os" >&5 +if eval "test \"`echo '$''{'ksh_cv_os_type'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ksh_cv_os_type=no + # Some tests below add -C to CPPFLAGS + saveCPPFLAGS="$CPPFLAGS" + for i in AIX ISC MINIX SCO OS2_EMX TITANOS NEXT HPUX; do + case $i in #(( + AIX) + cat > conftest.$ac_ext <&5 | + egrep "yes" >/dev/null 2>&1; then + rm -rf conftest* + ksh_cv_os_type=$i +fi +rm -f conftest* + + ;; #( + ISC) + # Both native ISC cpp and gcc understand this (leave comments in) + CPPFLAGS="$CPPFLAGS -C" + #XXX grep part won't work if cross-compiling... + cat > conftest.$ac_ext < +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "INTERACTIVE Systems Corporation" >/dev/null 2>&1; then + rm -rf conftest* + if grep _POSIX_VERSION /usr/include/sys/unistd.h > /dev/null 2>&1; then + ksh_cv_os_type="$i-posix" + else + ksh_cv_os_type=$i + fi +fi +rm -f conftest* + CPPFLAGS="$saveCPPFLAGS" + ;; #( + MINIX) + ac_safe=`echo "minix/config.h" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for minix/config.h""... $ac_c" 1>&6 +echo "configure:1033: checking for minix/config.h" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1043: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ksh_cv_os_type=$i +else + echo "$ac_t""no" 1>&6 +fi + ;; #( + SCO) + # Both native SCO cpp and gcc understand this (leave comments in) + CPPFLAGS="$CPPFLAGS -C" + cat > conftest.$ac_ext < +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "The Santa Cruz Operation" >/dev/null 2>&1; then + rm -rf conftest* + ksh_cv_os_type=$i +fi +rm -f conftest* + CPPFLAGS="$saveCPPFLAGS" + ;; #( + OS2_EMX) + cat > conftest.$ac_ext <&5 | + egrep "yes" >/dev/null 2>&1; then + rm -rf conftest* + ksh_cv_os_type=$i +fi +rm -f conftest* + ;; #( + TITANOS) + cat > conftest.$ac_ext <&5 | + egrep "YesTitan" >/dev/null 2>&1; then + rm -rf conftest* + ksh_cv_os_type=$i +fi +rm -f conftest* + ;; #( + NEXT) + # + # NeXT 3.2 (other versions?) - cc -E doesn't work and /lib/cpp + # doesn't define things that need defining, so tests that rely + # on $CPP will break. + # + # Hmmm - can't safely use CPP to test for NeXT defines, so have + # to use a program that won't compile on a NeXT and one that will + # only compile on a NeXT... + cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then + : +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ksh_cv_os_type=$i +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 +fi +rm -f conftest* +fi +rm -f conftest* ;; #( + HPUX) + cat > conftest.$ac_ext <&5 | + egrep "yes" >/dev/null 2>&1; then + rm -rf conftest* + ksh_cv_os_type=$i +fi +rm -f conftest* + + ;; #( + esac #)) + test $ksh_cv_os_type != no && break + done + +fi + +echo "$ac_t""$ksh_cv_os_type" 1>&6 + case $ksh_cv_os_type in #(( + AIX) + cat >> confdefs.h <<\EOF +#define _ALL_SOURCE 1 +EOF + ;; #( + ISC) + cat >> confdefs.h <<\EOF +#define OS_ISC 1 +EOF + ;; #( + ISC-posix) + cat >> confdefs.h <<\EOF +#define OS_ISC 1 +EOF + cat >> confdefs.h <<\EOF +#define _POSIX_SOURCE 1 +EOF + if test "$GCC" = yes; then + CC="$CC -posix" + else + CC="$CC -Xp" + fi + ;; #( + MINIX) + cat >> confdefs.h <<\EOF +#define _POSIX_SOURCE 1 +EOF + cat >> confdefs.h <<\EOF +#define _POSIX_1_SOURCE 2 +EOF + cat >> confdefs.h <<\EOF +#define _MINIX 1 +EOF + ;; #( + SCO) + cat >> confdefs.h <<\EOF +#define OS_SCO 1 +EOF + ;; #( + OS2_EMX) + # XXX change this to OS_OS2 or OS_OS2_EMX? + cat >> confdefs.h <<\EOF +#define OS2 1 +EOF + ac_exe_suffix=.exe + ;; #( + TITANOS) + # Need to use cc -43 to get a shell with job control + case "$CC" in #(( + *-43*) # Already have -43 option? + ;; #( + */cc|*/cc' '|*/cc' '|cc|cc' '|cc' ') # Using stock compiler? + CC="$CC -43" + ;; #( + esac #)) + # + # Force dirent check to find the right thing. There is a dirent.h + # (and a sys/dirent.h) file which compiles, but generates garbage... + # + ac_cv_header_dirent_dirent_h=no + ac_cv_header_dirent_sys_ndir_h=no + ac_cv_header_dirent_sys_dir_h=yes + ;; #( + NEXT) + # + # NeXT 3.2 (other versions?) - cc -E doesn't work and /lib/cpp + # doesn't define things that need defining, so tests that rely + # on $CPP will break. + # + cat > conftest.$ac_ext < + #if !defined(SIGINT) || !defined(SIGQUIT) + Bad NeXT + #endif + +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "Bad NeXT" >/dev/null 2>&1; then + rm -rf conftest* + { echo "configure: error: +There is a problem on NeXT boxes resulting in a bad siglist.out file being +generated (which breaks the trap and kill commands) and probably resulting +in many configuration tests not working correctly. + +You appear to have this problem - see the comments on NeXT in the pdksh +README file for work arounds." 1>&2; exit 1; } +fi +rm -f conftest* + ;; #( + HPUX) + # + # In some versions of hpux (eg, 10.2), getwd & getcwd will dump core + # if directory is not readble. + # + # name is used in test program + echo $ac_n "checking for bug in getwd""... $ac_c" 1>&6 +echo "configure:1287: checking for bug in getwd" >&5 +if eval "test \"`echo '$''{'ksh_cv_hpux_getwd_bug'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + tmpdir=conftest.dir + if mkdir $tmpdir ; then + if test "$cross_compiling" = yes; then + echo "configure: warning: assuming getwd broken" 1>&2; ksh_cv_hpux_getwd_bug=yes +else +cat > conftest.$ac_ext </dev/null; then + ksh_cv_hpux_getwd_bug=no +else + ksh_cv_hpux_getwd_bug=yes +fi +fi +rm -fr conftest* + test -d $tmpdir && rmdir $tmpdir + else + { echo "configure: error: could not make temp directory for test" 1>&2; exit 1; }; ksh_cv_hpux_getwd_bug=yes + fi +fi + +echo "$ac_t""$ksh_cv_hpux_getwd_bug" 1>&6 + if test $ksh_cv_hpux_getwd_bug = yes; then + cat >> confdefs.h <<\EOF +#define HPUX_GETWD_BUG 1 +EOF + + fi + ;; #( + esac #)) + +if test "$program_transform_name" = s,x,x,; then + program_transform_name= +else + # Double any \ or $. echo might interpret backslashes. + cat <<\EOF_SED > conftestsed +s,\\,\\\\,g; s,\$,$$,g +EOF_SED + program_transform_name="`echo $program_transform_name|sed -f conftestsed`" + rm -f conftestsed +fi +test "$program_prefix" != NONE && + program_transform_name="s,^,${program_prefix},; $program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s,\$\$,${program_suffix},; $program_transform_name" + +# sed with no file args requires a program. +test "$program_transform_name" = "" && program_transform_name="s,x,x," + +ac_header_dirent=no +for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr that defines DIR""... $ac_c" 1>&6 +echo "configure:1376: checking for $ac_hdr that defines DIR" >&5 +if eval "test \"`echo '$''{'ac_cv_header_dirent_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include <$ac_hdr> +int main() { +DIR *dirp = 0; +; return 0; } +EOF +if { (eval echo configure:1389: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + eval "ac_cv_header_dirent_$ac_safe=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_dirent_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_dirent_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done +# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. +if test $ac_header_dirent = dirent.h; then +echo $ac_n "checking for opendir in -ldir""... $ac_c" 1>&6 +echo "configure:1414: checking for opendir in -ldir" >&5 +ac_lib_var=`echo dir'_'opendir | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-ldir $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + LIBS="$LIBS -ldir" +else + echo "$ac_t""no" 1>&6 +echo $ac_n "checking for opendir in -lndir""... $ac_c" 1>&6 +echo "configure:1452: checking for opendir in -lndir" >&5 +ac_lib_var=`echo ndir'_'opendir | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lndir $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + LIBS="$LIBS -lndir" +else + echo "$ac_t""no" 1>&6 +fi + +fi + +else +echo $ac_n "checking for opendir in -lx""... $ac_c" 1>&6 +echo "configure:1495: checking for opendir in -lx" >&5 +ac_lib_var=`echo x'_'opendir | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lx $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + LIBS="$LIBS -lx" +else + echo "$ac_t""no" 1>&6 +fi + +fi + +echo $ac_n "checking for sane unistd.h""... $ac_c" 1>&6 +echo "configure:1537: checking for sane unistd.h" >&5 +if eval "test \"`echo '$''{'ksh_cv_header_unistd'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#if defined(_POSIX_VERSION) +# include +# include /* _POSIX_VERSION => HAVE_DIRENT_H test not needed */ +#endif + +int main() { + +; return 0; } +EOF +if { (eval echo configure:1555: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ksh_cv_header_unistd=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ksh_cv_header_unistd=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ksh_cv_header_unistd" 1>&6 + if test $ksh_cv_header_unistd = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_UNISTD_H 1 +EOF + + fi + +echo $ac_n "checking terminal interface""... $ac_c" 1>&6 +echo "configure:1576: checking terminal interface" >&5 +if eval "test \"`echo '$''{'ksh_cv_term_check'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +int main() { + + struct termios t; +#if defined(ultrix) || defined(__ultrix__) + Termios in ultrix 4.2 botches type-ahead when going from cooked to + cbreak mode. The BSD tty interface works fine though, so use it + (would be good to know if alter versions of ultrix work). +#endif /* ultrix */ + tcgetattr(0, &t); tcsetattr(0, TCSADRAIN, &t); + +; return 0; } +EOF +if { (eval echo configure:1596: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + ksh_cv_term_check=termios +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + cat > conftest.$ac_ext < +int main() { + + struct sgttyb sb; ioctl(0, TIOCGETP, &sb); +#ifdef TIOCGATC + { struct ttychars lc; ioctl(0, TIOCGATC, &lc); } +#else /* TIOCGATC */ + { struct tchars tc; ioctl(0, TIOCGETC, &tc); } +# ifdef TIOCGLTC + { struct ltchars ltc; ioctl(0, TIOCGLTC, <c); } +# endif /* TIOCGLTC */ +#endif /* TIOCGATC */ + +; return 0; } +EOF +if { (eval echo configure:1621: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + ksh_cv_term_check=bsd +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_safe=`echo "termio.h" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for termio.h""... $ac_c" 1>&6 +echo "configure:1630: checking for termio.h" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1640: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ksh_cv_term_check=termio +else + echo "$ac_t""no" 1>&6 +ksh_cv_term_check=sgtty +fi + +fi +rm -f conftest* +fi +rm -f conftest* +fi + +echo "$ac_t""$ksh_cv_term_check" 1>&6 + if test $ksh_cv_term_check = termios; then + cat >> confdefs.h <<\EOF +#define HAVE_TERMIOS_H 1 +EOF + + elif test $ksh_cv_term_check = termio; then + cat >> confdefs.h <<\EOF +#define HAVE_TERMIO_H 1 +EOF + + fi + +for ac_hdr in stddef.h stdlib.h string.h memory.h fcntl.h limits.h paths.h \ + sys/param.h sys/resource.h values.h ulimit.h sys/time.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:1686: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1696: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + +echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6 +echo "configure:1723: checking whether time.h and sys/time.h may both be included" >&5 +if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include +#include +int main() { +struct tm *tp; +; return 0; } +EOF +if { (eval echo configure:1737: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_header_time=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_header_time=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_header_time" 1>&6 +if test $ac_cv_header_time = yes; then + cat >> confdefs.h <<\EOF +#define TIME_WITH_SYS_TIME 1 +EOF + +fi + +echo $ac_n "checking for sys/wait.h that is POSIX.1 compatible""... $ac_c" 1>&6 +echo "configure:1758: checking for sys/wait.h that is POSIX.1 compatible" >&5 +if eval "test \"`echo '$''{'ksh_cv_header_sys_wait_h'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include +#ifndef WEXITSTATUS +#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) +#endif +#ifndef WIFEXITED +#define WIFEXITED(stat_val) (((stat_val) & 255) == 0) +#endif +int main() { +int s; +wait (&s); +s = WIFEXITED (s) ? WEXITSTATUS (s) : 1; +; return 0; } +EOF +if { (eval echo configure:1779: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ksh_cv_header_sys_wait_h=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ksh_cv_header_sys_wait_h=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ksh_cv_header_sys_wait_h" 1>&6 +if test $ksh_cv_header_sys_wait_h = yes; then + cat >> confdefs.h <<\EOF +#define POSIX_SYS_WAIT 1 +EOF + cat >> confdefs.h <<\EOF +#define HAVE_SYS_WAIT_H 1 +EOF +else + for ac_hdr in sys/wait.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:1804: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1814: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done +fi + +echo $ac_n "checking for off_t in sys/types.h""... $ac_c" 1>&6 +echo "configure:1842: checking for off_t in sys/types.h" >&5 +if eval "test \"`echo '$''{'ac_cv_type_off_t'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#if STDC_HEADERS +#include +#endif + + +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "(^|[^a-zA-Z0-9_])off_t([^a-zA-Z0-9_]|\$)" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_type_off_t=yes +else + rm -rf conftest* + ac_cv_type_off_t=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_type_off_t" 1>&6 + if test $ac_cv_type_off_t = no; then + cat >> confdefs.h <<\EOF +#define off_t long +EOF + + fi + +echo $ac_n "checking for mode_t in sys/types.h""... $ac_c" 1>&6 +echo "configure:1877: checking for mode_t in sys/types.h" >&5 +if eval "test \"`echo '$''{'ac_cv_type_mode_t'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#if STDC_HEADERS +#include +#endif + + +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "(^|[^a-zA-Z0-9_])mode_t([^a-zA-Z0-9_]|\$)" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_type_mode_t=yes +else + rm -rf conftest* + ac_cv_type_mode_t=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_type_mode_t" 1>&6 + if test $ac_cv_type_mode_t = no; then + cat >> confdefs.h <<\EOF +#define mode_t short +EOF + + fi + +echo $ac_n "checking for pid_t in sys/types.h""... $ac_c" 1>&6 +echo "configure:1912: checking for pid_t in sys/types.h" >&5 +if eval "test \"`echo '$''{'ac_cv_type_pid_t'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#if STDC_HEADERS +#include +#endif + + +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "(^|[^a-zA-Z0-9_])pid_t([^a-zA-Z0-9_]|\$)" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_type_pid_t=yes +else + rm -rf conftest* + ac_cv_type_pid_t=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_type_pid_t" 1>&6 + if test $ac_cv_type_pid_t = no; then + cat >> confdefs.h <<\EOF +#define pid_t int +EOF + + fi + +echo $ac_n "checking for uid_t in sys/types.h""... $ac_c" 1>&6 +echo "configure:1947: checking for uid_t in sys/types.h" >&5 +if eval "test \"`echo '$''{'ac_cv_type_uid_t'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#if STDC_HEADERS +#include +#endif + + +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "(^|[^a-zA-Z0-9_])uid_t([^a-zA-Z0-9_]|\$)" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_type_uid_t=yes +else + rm -rf conftest* + ac_cv_type_uid_t=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_type_uid_t" 1>&6 + if test $ac_cv_type_uid_t = no; then + cat >> confdefs.h <<\EOF +#define uid_t int +EOF + + fi + +if test $ac_cv_type_uid_t = no; then + cat >> confdefs.h <<\EOF +#define gid_t int +EOF + +fi + +echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6 +echo "configure:2057: checking return type of signal handlers" >&5 +if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include +#ifdef signal +#undef signal +#endif +#ifdef __cplusplus +extern "C" void (*signal (int, void (*)(int)))(int); +#else +void (*signal ()) (); +#endif + +int main() { +int i; +; return 0; } +EOF +if { (eval echo configure:2079: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_type_signal=void +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_type_signal=int +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_type_signal" 1>&6 +cat >> confdefs.h <&2; exit 1; } +esac +cat >> confdefs.h <&6 +echo "configure:2108: checking size of int" >&5 +if eval "test \"`echo '$''{'ac_cv_sizeof_int'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } +else +cat > conftest.$ac_ext < +main() +{ + FILE *f=fopen("conftestval", "w"); + if (!f) exit(1); + fprintf(f, "%d\n", sizeof(int)); + exit(0); +} +EOF +eval $ac_link +if test -s conftest$ac_exe_suffix && (./conftest; exit) 2>/dev/null; then + ac_cv_sizeof_int=`cat conftestval` +else + ac_cv_sizeof_int=0 +fi +fi +rm -fr conftest* +fi +echo "$ac_t""$ac_cv_sizeof_int" 1>&6 +cat >> confdefs.h <&6 +echo "configure:2143: checking size of long" >&5 +if eval "test \"`echo '$''{'ac_cv_sizeof_long'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } +else +cat > conftest.$ac_ext < +main() +{ + FILE *f=fopen("conftestval", "w"); + if (!f) exit(1); + fprintf(f, "%d\n", sizeof(long)); + exit(0); +} +EOF +eval $ac_link +if test -s conftest$ac_exe_suffix && (./conftest; exit) 2>/dev/null; then + ac_cv_sizeof_long=`cat conftestval` +else + ac_cv_sizeof_long=0 +fi +fi +rm -fr conftest* +fi +echo "$ac_t""$ac_cv_sizeof_long" 1>&6 +cat >> confdefs.h <, and ""... $ac_c" 1>&6 +echo "configure:2178: checking for clock_t in any of , and " >&5 +if eval "test \"`echo '$''{'ac_cv_type_clock_t'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#if STDC_HEADERS +#include +#endif + +#ifdef HAVE_SYS_TIME_H +#include +#endif /* HAVE_SYS_TIME_H */ +#include + + +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "(^|[^a-zA-Z0-9_])clock_t([^a-zA-Z0-9_]|\$)" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_type_clock_t=yes +else + rm -rf conftest* + ac_cv_type_clock_t=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_type_clock_t" 1>&6 + if test $ac_cv_type_clock_t = no; then + cat >> confdefs.h <<\EOF +#define clock_t INT32 +EOF + + fi + +echo $ac_n "checking for sigset_t in and ""... $ac_c" 1>&6 +echo "configure:2218: checking for sigset_t in and " >&5 +if eval "test \"`echo '$''{'ac_cv_type_sigset_t'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#if STDC_HEADERS +#include +#endif +#include + +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "(^|[^a-zA-Z0-9_])sigset_t([^a-zA-Z0-9_]|\$)" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_type_sigset_t=yes +else + rm -rf conftest* + ac_cv_type_sigset_t=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_type_sigset_t" 1>&6 + if test $ac_cv_type_sigset_t = no; then + cat >> confdefs.h <<\EOF +#define sigset_t unsigned +EOF + + fi + +echo $ac_n "checking for rlim_t in and ""... $ac_c" 1>&6 +echo "configure:2253: checking for rlim_t in and " >&5 +if eval "test \"`echo '$''{'ac_cv_type_rlim_t'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#if STDC_HEADERS +#include +#endif +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif + +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "(^|[^a-zA-Z0-9_])rlim_t([^a-zA-Z0-9_]|\$)" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_type_rlim_t=yes +else + rm -rf conftest* + ac_cv_type_rlim_t=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_type_rlim_t" 1>&6 + if test $ac_cv_type_rlim_t = no; then + echo $ac_n "checking what to set rlim_t to""... $ac_c" 1>&6 +echo "configure:2284: checking what to set rlim_t to" >&5 + if test $ac_cv_header_sys_resource_h = yes; then + if eval "test \"`echo '$''{'ksh_cv_rlim_check'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + { echo "configure: error: cannot determine type for rlimt_t when cross compiling" 1>&2; exit 1; } + +else +cat > conftest.$ac_ext < +#include +#include + main() + { + struct rlimit rl; + if (sizeof(rl.rlim_cur) == sizeof(quad_t)) + exit(0); + exit(1); + } + +EOF +eval $ac_link +if test -s conftest$ac_exe_suffix && (./conftest; exit) 2>/dev/null; then + ksh_cv_rlim_check=quad_t +else + ksh_cv_rlim_check=long +fi +fi +rm -fr conftest* +fi + else + ksh_cv_rlim_check=long + fi + echo "$ac_t""$ksh_cv_rlim_check" 1>&6 + cat >> confdefs.h <&6 +echo "configure:2329: checking for working memmove" >&5 +if eval "test \"`echo '$''{'ksh_cv_func_memmove'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + echo "configure: warning: assuming memmove broken" 1>&2; ksh_cv_func_memmove=no +else +cat > conftest.$ac_ext < +#else +# include +#endif +#ifdef HAVE_MEMORY_H +# include +#endif + int + main() + { + char buf[16]; + strcpy(buf, "abcdefABCDEF"); + memmove(buf + 4, buf, 6); + if (strcmp(buf, "abcdabcdefEF")) + exit(1); + memmove(buf, buf + 4, 6); + if (strcmp(buf, "abcdefcdefEF")) + exit(2); + exit(0); + return 0; + } +EOF +eval $ac_link +if test -s conftest$ac_exe_suffix && (./conftest; exit) 2>/dev/null; then + ksh_cv_func_memmove=yes +else + ksh_cv_func_memmove=no +fi +fi +rm -fr conftest* +fi + +echo "$ac_t""$ksh_cv_func_memmove" 1>&6 + if test $ksh_cv_func_memmove = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_MEMMOVE 1 +EOF + + else + echo $ac_n "checking for working bcopy""... $ac_c" 1>&6 +echo "configure:2381: checking for working bcopy" >&5 +if eval "test \"`echo '$''{'ksh_cv_func_bcopy'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + echo "configure: warning: assuming bcopy broken" 1>&2; ksh_cv_func_bcopy=no +else +cat > conftest.$ac_ext < +#else +# include +#endif +#ifdef HAVE_MEMORY_H +# include +#endif + int + main() + { + char buf[16]; + strcpy(buf, "abcdefABCDEF"); + bcopy(buf, buf + 4, 6); + if (strcmp(buf, "abcdabcdefEF")) + exit(1); + bcopy(buf + 4, buf, 6); + if (strcmp(buf, "abcdefcdefEF")) + exit(2); + exit(0); + } +EOF +eval $ac_link +if test -s conftest$ac_exe_suffix && (./conftest; exit) 2>/dev/null; then + ksh_cv_func_bcopy=yes +else + ksh_cv_func_bcopy=no +fi +fi +rm -fr conftest* +fi + +echo "$ac_t""$ksh_cv_func_bcopy" 1>&6 + if test $ksh_cv_func_bcopy = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_BCOPY 1 +EOF + + fi + fi + +echo $ac_n "checking for memset""... $ac_c" 1>&6 +echo "configure:2434: checking for memset" >&5 +if eval "test \"`echo '$''{'ksh_cv_func_memset'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#else +# include +#endif +#ifdef HAVE_MEMORY_H +# include +#endif + +int main() { + + char buf[16]; memset(buf, 'x', 7); printf("%7s", buf); +; return 0; } +EOF +if { (eval echo configure:2456: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + ksh_cv_func_memset=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ksh_cv_func_memset=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ksh_cv_func_memset" 1>&6 + if test $ksh_cv_func_memset = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_MEMSET 1 +EOF + + fi + +for ac_func in confstr dup2 flock getcwd getwd killpg nice \ + setrlimit strerror strcasecmp strstr sysconf tcsetpgrp \ + ulimit waitpid wait3 +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:2481: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2509: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + +for ac_func in sigsetjmp _setjmp +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:2536: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2564: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + +for ac_func in valloc getpagesize +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:2591: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2619: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + +echo $ac_n "checking for working mmap""... $ac_c" 1>&6 +echo "configure:2644: checking for working mmap" >&5 +if eval "test \"`echo '$''{'ac_cv_func_mmap'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + ac_cv_func_mmap=no +else +cat > conftest.$ac_ext < +#include +#include + +#ifndef HAVE_GETPAGESIZE +# include +# ifdef EXEC_PAGESIZE +# define getpagesize() EXEC_PAGESIZE +# else +# ifdef NBPG +# define getpagesize() NBPG * CLSIZE +# ifndef CLSIZE +# define CLSIZE 1 +# endif +# else +# ifdef NBPC +# define getpagesize() NBPC +# else +# define getpagesize() PAGESIZE /* SVR4 */ +# endif +# endif +# endif +#endif + +#ifndef HAVE_VALLOC +# define valloc malloc +#endif + +#ifdef __cplusplus +extern "C" { void *valloc(unsigned), *malloc(unsigned); } +#else +char *valloc(), *malloc(); +#endif + +#ifndef MAP_FILE +# define MAP_FILE 0 +#endif /* MAP_FILE */ + +int +main() +{ + char *buf1, *buf2, *buf3; + int i = getpagesize(), j; + int i2 = i * 2; + int fd; + + buf1 = (char *)valloc(i2); + buf2 = (char *)valloc(i); + buf3 = (char *)malloc(i2); + for (j = 0; j < i2; ++j) + *(buf1 + j) = rand(); + fd = open("conftestmmap", O_CREAT | O_RDWR, 0666); + write(fd, buf1, i2); + mmap(buf2, i, PROT_READ | PROT_WRITE, MAP_FILE | MAP_FIXED | MAP_PRIVATE, fd, 0); + for (j = 0; j < i; ++j) + if (*(buf1 + j) != *(buf2 + j)) + exit(1); + lseek(fd, (long)i, 0); + read(fd, buf2, i); /* read into mapped memory -- file should not change */ + /* (it does in i386 SVR4.0 - Jim Avera, jima@netcom.com) */ + lseek(fd, (long)0, 0); + read(fd, buf3, i2); + for (j = 0; j < i2; ++j) + if (*(buf1 + j) != *(buf3 + j)) + exit(1); + exit(0); +} + +EOF +eval $ac_link +if test -s conftest$ac_exe_suffix && (./conftest; exit) 2>/dev/null; then + ac_cv_func_mmap=yes +else + ac_cv_func_mmap=no +fi +fi +rm -fr conftest* +fi + +echo "$ac_t""$ac_cv_func_mmap" 1>&6 +if test $ac_cv_func_mmap = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_MMAP 1 +EOF + +fi + +echo $ac_n "checking for lstat""... $ac_c" 1>&6 +echo "configure:2744: checking for lstat" >&5 +if eval "test \"`echo '$''{'ksh_cv_func_lstat'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include + +int main() { + + struct stat statb; + lstat("/", &statb); + +; return 0; } +EOF +if { (eval echo configure:2762: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + ksh_cv_func_lstat=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ksh_cv_func_lstat=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ksh_cv_func_lstat" 1>&6 +if test $ksh_cv_func_lstat = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_LSTAT 1 +EOF + +fi + +echo $ac_n "checking for sys_errlist declaration in errno.h""... $ac_c" 1>&6 +echo "configure:2783: checking for sys_errlist declaration in errno.h" >&5 +if eval "test \"`echo '$''{'ksh_cv_decl_sys_errlist'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +int main() { +char *msg = *(sys_errlist + 1); if (msg && *msg) return 12; +; return 0; } +EOF +if { (eval echo configure:2795: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ksh_cv_decl_sys_errlist=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ksh_cv_decl_sys_errlist=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ksh_cv_decl_sys_errlist" 1>&6 + if test $ksh_cv_decl_sys_errlist = yes; then + cat >> confdefs.h <<\EOF +#define SYS_ERRLIST_DECLARED 1 +EOF + + cat >> confdefs.h <<\EOF +#define HAVE_SYS_ERRLIST 1 +EOF + + else + echo $ac_n "checking for sys_errlist in library""... $ac_c" 1>&6 +echo "configure:2819: checking for sys_errlist in library" >&5 +if eval "test \"`echo '$''{'ksh_cv_var_sys_errlist'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + ksh_cv_var_sys_errlist=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ksh_cv_var_sys_errlist=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ksh_cv_var_sys_errlist" 1>&6 + if test $ksh_cv_var_sys_errlist = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_SYS_ERRLIST 1 +EOF + + fi + fi + +echo $ac_n "checking for sys_siglist declaration in signal.h or unistd.h""... $ac_c" 1>&6 +echo "configure:2859: checking for sys_siglist declaration in signal.h or unistd.h" >&5 +if eval "test \"`echo '$''{'ac_cv_decl_sys_siglist'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include +/* NetBSD declares sys_siglist in unistd.h. */ +#ifdef HAVE_UNISTD_H +#include +#endif +int main() { +char *msg = *(sys_siglist + 1); +; return 0; } +EOF +if { (eval echo configure:2876: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_decl_sys_siglist=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_decl_sys_siglist=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_decl_sys_siglist" 1>&6 +if test $ac_cv_decl_sys_siglist = yes; then + cat >> confdefs.h <<\EOF +#define SYS_SIGLIST_DECLARED 1 +EOF + +fi + + if test ac_cv_decl_sys_siglist = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_SYS_SIGLIST 1 +EOF + + else + echo $ac_n "checking for sys_siglist in library""... $ac_c" 1>&6 +echo "configure:2903: checking for sys_siglist in library" >&5 +if eval "test \"`echo '$''{'ksh_cv_var_sys_siglist'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + ksh_cv_var_sys_siglist=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ksh_cv_var_sys_siglist=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ksh_cv_var_sys_siglist" 1>&6 + if test $ksh_cv_var_sys_siglist = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_SYS_SIGLIST 1 +EOF + + fi + fi + +echo $ac_n "checking time() declaration in time.h""... $ac_c" 1>&6 +echo "configure:2942: checking time() declaration in time.h" >&5 +if eval "test \"`echo '$''{'ksh_cv_time_delcared'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include +int main() { +time_t (*f)() = time; if (f) return 12; +; return 0; } +EOF +if { (eval echo configure:2955: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ksh_cv_time_delcared=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ksh_cv_time_delcared=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ksh_cv_time_delcared" 1>&6 + if test $ksh_cv_time_delcared = yes; then + cat >> confdefs.h <<\EOF +#define TIME_DECLARED 1 +EOF + + fi + +echo $ac_n "checking if times() is present/working""... $ac_c" 1>&6 +echo "configure:2976: checking if times() is present/working" >&5 +if eval "test \"`echo '$''{'ksh_cv_func_times_ok'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + { echo "configure: error: cannot determine if times works when cross compiling" 1>&2; exit 1; } + +else +cat > conftest.$ac_ext < +#include +/* if missing, clock_t is defined to be INT32 */ +#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 */ + main() + { + extern clock_t times(); + struct tms tms; + times(&tms); + sleep(1); + if (times(&tms) == 0) + exit(1); + exit(0); + } + +EOF +eval $ac_link +if test -s conftest$ac_exe_suffix && (./conftest; exit) 2>/dev/null; then + ksh_cv_func_times_ok=yes +else + ksh_cv_func_times_ok=no +fi +fi +rm -fr conftest* +fi + +echo "$ac_t""$ksh_cv_func_times_ok" 1>&6 + if test $ksh_cv_func_times_ok = no; then + cat >> confdefs.h <<\EOF +#define TIMES_BROKEN 1 +EOF + + for ac_func in getrusage +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:3031: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:3059: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + + fi + +echo $ac_n "checking whether stat file-mode macros are broken""... $ac_c" 1>&6 +echo "configure:3086: checking whether stat file-mode macros are broken" >&5 +if eval "test \"`echo '$''{'ac_cv_header_stat_broken'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include + +#if defined(S_ISBLK) && defined(S_IFDIR) +# if S_ISBLK (S_IFDIR) +You lose. +# endif +#endif + +#if defined(S_ISBLK) && defined(S_IFCHR) +# if S_ISBLK (S_IFCHR) +You lose. +# endif +#endif + +#if defined(S_ISLNK) && defined(S_IFREG) +# if S_ISLNK (S_IFREG) +You lose. +# endif +#endif + +#if defined(S_ISSOCK) && defined(S_IFREG) +# if S_ISSOCK (S_IFREG) +You lose. +# endif +#endif + +#if defined(S_ISSOCK) && defined(S_IFIFO) +# if S_ISSOCK (S_IFIFO) +You lose. +# endif +#endif + +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "You lose" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_header_stat_broken=yes +else + rm -rf conftest* + ac_cv_header_stat_broken=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_header_stat_broken" 1>&6 +if test $ac_cv_header_stat_broken = yes; then + cat >> confdefs.h <<\EOF +#define STAT_MACROS_BROKEN 1 +EOF + +fi + +echo $ac_n "checking for st_rdev in struct stat""... $ac_c" 1>&6 +echo "configure:3148: checking for st_rdev in struct stat" >&5 +if eval "test \"`echo '$''{'ac_cv_struct_st_rdev'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include +int main() { +struct stat s; s.st_rdev; +; return 0; } +EOF +if { (eval echo configure:3161: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_struct_st_rdev=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_struct_st_rdev=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_struct_st_rdev" 1>&6 +if test $ac_cv_struct_st_rdev = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_ST_RDEV 1 +EOF + +fi + +echo $ac_n "checking for working const""... $ac_c" 1>&6 +echo "configure:3182: checking for working const" >&5 +if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <j = 5; +} +{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; +} + +; return 0; } +EOF +if { (eval echo configure:3236: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_c_const=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_c_const=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_c_const" 1>&6 +if test $ac_cv_c_const = no; then + cat >> confdefs.h <<\EOF +#define const +EOF + +fi + +echo $ac_n "checking if compiler understands void""... $ac_c" 1>&6 +echo "configure:3257: checking if compiler understands void" >&5 +if eval "test \"`echo '$''{'ksh_cv_c_void'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ksh_cv_c_void=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ksh_cv_c_void=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ksh_cv_c_void" 1>&6 + if test $ksh_cv_c_void = yes; then + : + else + cat >> confdefs.h <<\EOF +#define void char +EOF + + fi + +echo $ac_n "checking if compiler understands volatile""... $ac_c" 1>&6 +echo "configure:3296: checking if compiler understands volatile" >&5 +if eval "test \"`echo '$''{'ksh_cv_c_volatile'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ksh_cv_c_volatile=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ksh_cv_c_volatile=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ksh_cv_c_volatile" 1>&6 + if test $ksh_cv_c_volatile = yes; then + : + else + cat >> confdefs.h <<\EOF +#define volatile +EOF + + fi + +echo $ac_n "checking if compiler understands prototypes""... $ac_c" 1>&6 +echo "configure:3333: checking if compiler understands prototypes" >&5 +if eval "test \"`echo '$''{'ksh_cv_c_prototypes'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +void foo(char *fmt, ...); +int bar(int a, char b, char *c); +int bar(a, b, c) int a; char b; char *c; +{ foo("%d%c%s\n", a, b, c); return a + b + *c; } +void foo(char *fmt, ...) { va_list a; va_start(a, fmt); va_end(a); } + +int main() { + +; return 0; } +EOF +if { (eval echo configure:3352: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ksh_cv_c_prototypes=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ksh_cv_c_prototypes=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ksh_cv_c_prototypes" 1>&6 + if test $ksh_cv_c_prototypes = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_PROTOTYPES 1 +EOF + + fi + +echo $ac_n "checking if C compiler groks __attribute__(( .. ))""... $ac_c" 1>&6 +echo "configure:3373: checking if C compiler groks __attribute__(( .. ))" >&5 +if eval "test \"`echo '$''{'ksh_cv_c_func_attr'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +void test_fmt(char *fmt, ...) __attribute__((format(printf, 1, 2))); +void test_fmt(char *fmt, ...) { return; } +int test_cnst(int) __attribute__((const)); +int test_cnst(int x) { return x + 1; } +void test_nr() __attribute__((noreturn)); +void test_nr() { exit(1); } +void test_uk() __attribute__((blah)); +void test_uk() { return; } + +int main() { +test_nr("%d", 10); test_cnst(2); test_uk(); test_nr(); +; return 0; } +EOF +if { (eval echo configure:3395: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ksh_cv_c_func_attr=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ksh_cv_c_func_attr=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ksh_cv_c_func_attr" 1>&6 + if test $ksh_cv_c_func_attr = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_GCC_FUNC_ATTR 1 +EOF + + fi + +# Pull the hash mark out of the macro call to avoid m4 problems. +ac_msg="whether #! works in shell scripts" +echo $ac_n "checking $ac_msg""... $ac_c" 1>&6 +echo "configure:3418: checking $ac_msg" >&5 +if eval "test \"`echo '$''{'ac_cv_sys_interpreter'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo '#! /bin/cat +exit 69 +' > conftest +chmod u+x conftest +(SHELL=/bin/sh; export SHELL; ./conftest >/dev/null) +if test $? -ne 69; then + ac_cv_sys_interpreter=yes +else + ac_cv_sys_interpreter=no +fi +rm -f conftest +fi + +echo "$ac_t""$ac_cv_sys_interpreter" 1>&6 + +if test $ac_cv_sys_interpreter = no; + then cat >> confdefs.h <<\EOF +#define SHARPBANG 1 +EOF + +fi +ac_aux_dir= +for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; } +fi +ac_config_guess=$ac_aux_dir/config.guess +ac_config_sub=$ac_aux_dir/config.sub +ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +echo "configure:3473: checking for a BSD compatible install" >&5 +if test -z "$INSTALL"; then +if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + for ac_prog in ginstall installbsd scoinst install; do + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + # OSF/1 installbsd also uses dspmsg, but is usable. + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + done + ;; + esac + done + IFS="$ac_save_IFS" + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL="$ac_cv_path_install" + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi +fi +echo "$ac_t""$INSTALL" 1>&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +echo $ac_n "checking if dup2() works (ie, resets the close-on-exec flag)""... $ac_c" 1>&6 +echo "configure:3523: checking if dup2() works (ie, resets the close-on-exec flag)" >&5 +if eval "test \"`echo '$''{'ksh_cv_dup2_clexec_ok'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + echo "configure: warning: cannot test if dup2 is broken when cross compiling - assuming it is" 1>&2 + ksh_cv_dup2_clexec_ok=no +else +cat > conftest.$ac_ext < +#ifdef HAVE_FCNTL_H +# include +#endif /* HAVE_FCNTL_H */ +#ifndef F_GETFD +# define F_GETFD 1 +#endif +#ifndef F_SETFD +# define F_SETFD 2 +#endif +#ifndef O_RDONLY +# define O_RDONLY 0 +#endif +/* On some systems (Ultrix 2.1..4.2 (and more?)), dup2() does not clear + the close on exec flag */ +main() +{ + int fd1, fd2; + fd1 = open("/dev/null", O_RDONLY); + if (fcntl(fd1, F_SETFD, 1) < 0) + exit(1); + fd2 = dup2(fd1, fd1 + 1); + if (fd2 < 0) + exit(2); + exit(fcntl(fd2, F_GETFD, 0) == 0 ? 0 : 3); +} + +EOF +eval $ac_link +if test -s conftest$ac_exe_suffix && (./conftest; exit) 2>/dev/null; then + ksh_cv_dup2_clexec_ok=yes +else + ksh_cv_dup2_clexec_ok=no +fi +fi +rm -fr conftest* +fi + +echo "$ac_t""$ksh_cv_dup2_clexec_ok" 1>&6 + if test $ksh_cv_dup2_clexec_ok = no; then + cat >> confdefs.h <<\EOF +#define DUP2_BROKEN 1 +EOF + + fi + +echo $ac_n "checking flavour of signal routines""... $ac_c" 1>&6 +echo "configure:3582: checking flavour of signal routines" >&5 +if eval "test \"`echo '$''{'ksh_cv_signal_check'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +int main() { + + sigset_t ss; + struct sigaction sa; + sigemptyset(&ss); sigsuspend(&ss); + sigaction(SIGINT, &sa, (struct sigaction *) 0); + sigprocmask(SIG_BLOCK, &ss, (sigset_t *) 0); + +; return 0; } +EOF +if { (eval echo configure:3600: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + ksh_cv_signal_check=posix +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + cat > conftest.$ac_ext < +int main() { + + int mask = sigmask(SIGINT); + sigsetmask(mask); sigblock(mask); sigpause(mask); + +; return 0; } +EOF +if { (eval echo configure:3618: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + ksh_cv_signal_check=bsd42 +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + cat > conftest.$ac_ext < + RETSIGTYPE foo() { } +int main() { + + int mask = sigmask(SIGINT); + sigset(SIGINT, foo); sigrelse(SIGINT); + sighold(SIGINT); sigpause(SIGINT); + +; return 0; } +EOF +if { (eval echo configure:3638: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + ksh_cv_signal_check=bsd41 +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ksh_cv_signal_check=v7 +fi +rm -f conftest* +fi +rm -f conftest* +fi +rm -f conftest* +fi + +echo "$ac_t""$ksh_cv_signal_check" 1>&6 + if test $ksh_cv_signal_check = posix; then + cat >> confdefs.h <<\EOF +#define POSIX_SIGNALS 1 +EOF + + else + cat >> confdefs.h <<\EOF +#define USE_FAKE_SIGACT 1 +EOF + + if test $ksh_cv_signal_check = bsd42; then + cat >> confdefs.h <<\EOF +#define BSD42_SIGNALS 1 +EOF + + elif test $ksh_cv_signal_check = bsd41; then + cat >> confdefs.h <<\EOF +#define BSD41_SIGNALS 1 +EOF + + echo $ac_n "checking if signals interrupt read()""... $ac_c" 1>&6 +echo "configure:3676: checking if signals interrupt read()" >&5 +if eval "test \"`echo '$''{'ksh_cv_signals_interrupt'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + { echo "configure: error: cannot determine if signals interrupt read() when cross compiling" 1>&2; exit 1; } + +else +cat > conftest.$ac_ext < +#include + + extern int errno; + int flag = 0; + + RETSIGTYPE + catcher(int sig) + { + flag = 1; + return RETSIGVAL; + } + + int + main() + { + int pid; + int fdc[2]; /* child writes to parent */ + int fdp[2]; /* parent writes to child */ + char buf; + int nread; + + if (pipe(fdc) < 0) + exit(1); + if (pipe(fdp) < 0) + exit(2); + if ((pid = fork()) < 0) + exit(3); + if (pid == 0) { + close(fdc[0]); + close(fdp[1]); + if (read(fdp[0], &buf, 1) != 0) + exit(10); + sleep(1); /* let parent into read */ + if (kill(getppid(), SIGALRM) < 0) + exit(11); + sleep(1); /* ensure parent gets to run */ + write(fdc[1], "1", 1); + close(fdc[1]); + exit(0); + } + close(fdc[1]); + close(fdp[0]); + + /* Use native routines for test as this is what the shell + * will be using... + */ +#ifdef POSIX_SIGNALS + { + struct sigaction sa, osa; + sa.sa_handler = catcher; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sigaction(SIGALRM, &sa, &osa); + } +#else /* POSIX_SIGNALS */ +# ifdef BSD42_SIGNALS + { + struct sigvec vec, ovec; + vec.sv_handler = catcher; + vec.sv_mask = 0; + vec.sv_flags = 0; +# ifdef SV_INTERRUPT + vec.sv_flags |= SV_INTERRUPT; +# endif /* SV_INTERRUPT */ + sigvec(SIGALRM, &vec, &ovec); + } +# else /* BSD42_SIGNALS */ +# ifdef BSD41_SIGNALS + sigset(SIGALRM, catcher); +# else /* BSD41_SIGNALS */ +# ifdef V7_SIGNALS + signal(SIGALRM, catcher); +# else /* V7_SIGNALS */ + what kind of signals do you have? +# endif /* V7_SIGNALS */ +# endif /* BSD41_SIGNALS */ +# endif /* BSD42_SIGNALS */ +#endif /* POSIX_SIGNALS */ + close(fdp[1]); /* start child */ + nread = read(fdc[0], &buf, 1); + if (nread == 0) + exit(4); + if (nread > 0) + exit(5); + if (errno != EINTR) + exit(6); + if (!flag) + exit(7); + exit(0); + return 0; + } + +EOF +eval $ac_link +if test -s conftest$ac_exe_suffix && (./conftest; exit) 2>/dev/null; then + ksh_cv_signals_interrupt=yes +else + ksh_cv_signals_interrupt=no +fi +fi +rm -fr conftest* +fi + +echo "$ac_t""$ksh_cv_signals_interrupt" 1>&6 + if test $ksh_cv_signals_interrupt = no ; then + cat >> confdefs.h <<\EOF +#define SIGNALS_DONT_INTERRUPT 1 +EOF + + fi + else + cat >> confdefs.h <<\EOF +#define V7_SIGNALS 1 +EOF + + fi + fi + +echo $ac_n "checking flavour of pgrp routines""... $ac_c" 1>&6 +echo "configure:3808: checking flavour of pgrp routines" >&5 +if eval "test \"`echo '$''{'ksh_cv_pgrp_check'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + { echo "configure: error: cannot taste pgrp routines when cross compiling" 1>&2; exit 1; } +else +cat > conftest.$ac_ext < +#ifdef HAVE_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ + main() + { + int ecode = 0, child = fork(); + if (child < 0) + exit(1); + if (child == 0) { + signal(SIGTERM, SIG_DFL); /* just to make sure */ + sleep(10); + exit(9); + } + if (setpgrp(child, child) < 0) + ecode = 2; + else if (getpgrp(child) != child) + ecode = 3; + kill(child, SIGTERM); + exit(ecode); + } + +EOF +eval $ac_link +if test -s conftest$ac_exe_suffix && (./conftest; exit) 2>/dev/null; then + ksh_cv_pgrp_check=bsd +else + if test "$cross_compiling" = yes; then + { echo "configure: error: cannot taste pgrp routines when cross compiling" 1>&2; exit 1; } +else +cat > conftest.$ac_ext < +#endif /* HAVE_UNISTD_H */ + main() + { + int child; + int n, p1[2], p2[2]; + char buf[1]; + if (pipe(p1) < 0 || pipe(p2) < 0) + exit(1); + if ((child = fork()) < 0) + exit(2); + if (child == 0) { + n = read(p1[0], buf, sizeof(buf)); /* wait for parent to setpgid */ + buf[0] = (n != 1 ? 10 : (getpgrp() != getpid() ? 11 : 0)); + if (write(p2[1], buf, sizeof(buf)) != 1) + exit(12); + exit(0); + } + if (setpgid(child, child) < 0) + exit(3); + if (write(p1[1], buf, 1) != 1) + exit(4); + if (read(p2[0], buf, 1) != 1) + exit(5); + exit((int) buf[0]); + } + +EOF +eval $ac_link +if test -s conftest$ac_exe_suffix && (./conftest; exit) 2>/dev/null; then + ksh_cv_pgrp_check=posix +else + if test "$cross_compiling" = yes; then + { echo "configure: error: cannot taste pgrp routines when cross compiling" 1>&2; exit 1; } +else +cat > conftest.$ac_ext < +#endif /* HAVE_UNISTD_H */ + main() + { + int child; + int n, p[2]; + char buf[1]; + if (pipe(p) < 0) + exit(1); + if ((child = fork()) < 0) + exit(2); + if (child == 0) { + buf[0] = (setpgrp() < 0 ? 10 : (getpgrp() != getpid() ? 11 : 0)); + if (write(p[1], buf, sizeof(buf)) != 1) + exit(11); + exit(0); + } + if (read(p[0], buf, 1) != 1) + exit(3); + exit((int) buf[0]); + } + +EOF +eval $ac_link +if test -s conftest$ac_exe_suffix && (./conftest; exit) 2>/dev/null; then + ksh_cv_pgrp_check=sysv +else + ksh_cv_pgrp_check=none +fi +fi +rm -fr conftest* +fi +fi +rm -fr conftest* +fi +fi +rm -fr conftest* +fi + +echo "$ac_t""$ksh_cv_pgrp_check" 1>&6 + if test $ksh_cv_pgrp_check = bsd; then + cat >> confdefs.h <<\EOF +#define BSD_PGRP 1 +EOF + + elif test $ksh_cv_pgrp_check = posix; then + cat >> confdefs.h <<\EOF +#define POSIX_PGRP 1 +EOF + + elif test $ksh_cv_pgrp_check = sysv; then + cat >> confdefs.h <<\EOF +#define SYSV_PGRP 1 +EOF + + else + cat >> confdefs.h <<\EOF +#define NO_PGRP 1 +EOF + + fi + + if test $ksh_cv_pgrp_check = bsd || test $ksh_cv_pgrp_check = posix ; then + echo $ac_n "checking if process group synchronization is required""... $ac_c" 1>&6 +echo "configure:3961: checking if process group synchronization is required" >&5 +if eval "test \"`echo '$''{'ksh_cv_need_pgrp_sync'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + echo "configure: warning: cannot test if pgrp synchronization needed when cross compiling - assuming it is" 1>&2 + ksh_cv_need_pgrp_sync=yes +else +cat > conftest.$ac_ext </dev/null; then + ksh_cv_need_pgrp_sync=no +else + ksh_cv_need_pgrp_sync=yes +fi +fi +rm -fr conftest* +fi + +echo "$ac_t""$ksh_cv_need_pgrp_sync" 1>&6 + if test $ksh_cv_need_pgrp_sync = yes; then + cat >> confdefs.h <<\EOF +#define NEED_PGRP_SYNC 1 +EOF + + fi + fi + +echo $ac_n "checking if opendir() fails to open non-directories""... $ac_c" 1>&6 +echo "configure:4034: checking if opendir() fails to open non-directories" >&5 +if eval "test \"`echo '$''{'ksh_cv_opendir_ok'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + echo "configure: warning: cannot test if opendir opens non-directories when cross compiling - assuming it does" 1>&2 + ksh_cv_opendir_ok=no +else +cat > conftest.$ac_ext < +#include +#ifdef HAVE_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ +#if defined(HAVE_DIRENT_H) +# include +#else +# define dirent direct +# ifdef SYSNDIR +# include +# endif /* SYSNDIR */ +# ifdef SYSDIR +# include +# endif /* SYSDIR */ +# ifdef NDIR +# include +# endif /* NDIR */ +#endif /* DIRENT */ + main() + { + int i, ret = 0; + FILE *fp; + char *fname = "conftestod", buf[256]; + for (i = 0; i < sizeof(buf); i++) /* memset(buf, 0, sizeof(buf)) */ + buf[i] = 0; + unlink(fname); /* paranoia */ + i = ((fp = fopen(fname, "w")) == (FILE *) 0 && (ret = 1)) + || (fwrite(buf, sizeof(buf), 1, fp) != 1 && (ret = 2)) + || (fclose(fp) == EOF && (ret = 3)) + || (opendir(fname) && (ret = 4)) + || (opendir("/dev/null") && (ret = 5)); + unlink(fname); + exit(ret); + } + +EOF +eval $ac_link +if test -s conftest$ac_exe_suffix && (./conftest; exit) 2>/dev/null; then + ksh_cv_opendir_ok=yes +else + ksh_cv_opendir_ok=no +fi +fi +rm -fr conftest* +fi + +echo "$ac_t""$ksh_cv_opendir_ok" 1>&6 + if test $ksh_cv_opendir_ok = no; then + cat >> confdefs.h <<\EOF +#define OPENDIR_DOES_NONDIR 1 +EOF + + fi + +echo $ac_n "checking if you have /dev/fd/n""... $ac_c" 1>&6 +echo "configure:4102: checking if you have /dev/fd/n" >&5 +if eval "test \"`echo '$''{'ksh_cv_dev_fd'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + echo "configure: warning: cannot determine if you have /dev/fd support" 1>&2 + ksh_cv_dev_fd=no +else +cat > conftest.$ac_ext < +#include +#include + main() + { + struct stat s1, s2; + FILE *fp1, *fp2; + char *file = "conftest.file"; + char devfd[32]; + + if (!(fp1 = fopen(file, "w"))) + exit(1); + if (fstat(fileno(fp1), &s1) < 0) + exit(2); + sprintf(devfd, "/dev/fd/%d", fileno(fp1)); + if (!(fp2 = fopen(devfd, "w"))) + exit(3); + if (fstat(fileno(fp2), &s2) < 0) + exit(4); + if (s1.st_dev != s2.st_dev || s1.st_ino != s2.st_ino) + exit(5); + exit(0); + } + +EOF +eval $ac_link +if test -s conftest$ac_exe_suffix && (./conftest; exit) 2>/dev/null; then + ksh_cv_dev_fd=yes +else + ksh_cv_dev_fd=no +fi +fi +rm -fr conftest* +fi + +echo "$ac_t""$ksh_cv_dev_fd" 1>&6 + if test $ksh_cv_dev_fd = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_DEV_FD 1 +EOF + + fi + +if test X"$LDSTATIC" != X; then + LDFLAGS=`echo -- "$LDFLAGS" | sed -e 's/^-- //' -e 's?$LDSTATIC?\$(LDSTATIC)?'` +fi +trap '' 1 2 15 +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +DEFS=-DHAVE_CONFIG_H + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS </dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.12" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir +ac_given_INSTALL="$INSTALL" + +trap 'rm -fr `echo "Makefile config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@SHELL_PROG@%$SHELL_PROG%g +s%@CC@%$CC%g +s%@CPP@%$CPP%g +s%@LDSTATIC@%$LDSTATIC%g +s%@ac_exe_suffix@%$ac_exe_suffix%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_DATA@%$INSTALL_DATA%g + +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + case "$ac_given_INSTALL" in + [/$]*) INSTALL="$ac_given_INSTALL" ;; + *) INSTALL="$ac_dots$ac_given_INSTALL" ;; + esac + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +s%@INSTALL@%$INSTALL%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='\([ ][ ]*\)[^ ]*%\1#\2' +ac_dC='\3' +ac_dD='%g' +# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE". +ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='\([ ]\)%\1#\2define\3' +ac_uC=' ' +ac_uD='\4%g' +# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_eB='$%\1#\2define\3' +ac_eC=' ' +ac_eD='%g' + +if test "${CONFIG_HEADERS+set}" != set; then +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +fi +for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + echo creating $ac_file + + rm -f conftest.frag conftest.in conftest.out + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + cat $ac_file_inputs > conftest.in + +EOF + +# Transform confdefs.h into a sed script conftest.vals that substitutes +# the proper values into config.h.in to produce config.h. And first: +# Protect against being on the right side of a sed subst in config.status. +# Protect against being in an unquoted here document in config.status. +rm -f conftest.vals +cat > conftest.hdr <<\EOF +s/[\\&%]/\\&/g +s%[\\$`]%\\&%g +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp +s%ac_d%ac_u%gp +s%ac_u%ac_e%gp +EOF +sed -n -f conftest.hdr confdefs.h > conftest.vals +rm -f conftest.hdr + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >> conftest.vals <<\EOF +s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */% +EOF + +# Break up conftest.vals because some shells have a limit on +# the size of here documents, and old seds have small limits too. + +rm -f conftest.tail +while : +do + ac_lines=`grep -c . conftest.vals` + # grep -c gives empty output for an empty file on some AIX systems. + if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi + # Write a limited-size here document to conftest.frag. + echo ' cat > conftest.frag <> $CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS + echo 'CEOF + sed -f conftest.frag conftest.in > conftest.out + rm -f conftest.in + mv conftest.out conftest.in +' >> $CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail + rm -f conftest.vals + mv conftest.tail conftest.vals +done +rm -f conftest.vals + +cat >> $CONFIG_STATUS <<\EOF + rm -f conftest.frag conftest.h + echo "/* $ac_file. Generated automatically by configure. */" > conftest.h + cat conftest.in >> conftest.h + rm -f conftest.in + if cmp -s $ac_file conftest.h 2>/dev/null; then + echo "$ac_file is unchanged" + rm -f conftest.h + else + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + fi + rm -f $ac_file + mv conftest.h $ac_file + fi +fi; done + +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF + +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + diff --git a/configure.in b/configure.in new file mode 100644 index 0000000..4cf1c71 --- /dev/null +++ b/configure.in @@ -0,0 +1,328 @@ +dnl +dnl This file, configure.in, which is a part of pdksh (the public domain ksh), +dnl is placed in the public domain. It comes with no licence, warranty +dnl or guarantee of any kind (i.e., at your own risk). +dnl +dnl +dnl +dnl Process this file with autoconf to produce a configure script +dnl +AC_INIT(c_ksh.c) +AC_CONFIG_HEADER(config.h) +dnl +dnl +dnl +dnl Set up command line options (--enable/--disable) +dnl +def_path_unix="/bin:/usr/bin:/usr/ucb" +def_path_os2="c:/usr/bin;c:/os2;/os2" +AC_ARG_ENABLE(path, +[ --enable-path=PaTh (NOTE: this value isn't used if confstr() and _CS_PATH + are available, or if defines _PATH_DEFPATH) + Use PaTh if PATH isn't specified in the environment + when the shell starts. A value without . in it is + safest. + The default value is \"/bin:/usr/bin:/usr/ucb\".],, + enable_path=default) +case $enable_path:$ksh_cv_os_type in + default:OS2_EMX) enable_path="$def_path_os2" ;; + default:*) enable_path="$def_path_unix" ;; +esac +case $enable_path in + \"*\") ;; + *) + enable_path="\"$enable_path\"" + ;; +esac +AC_DEFINE_UNQUOTED(DEFAULT_PATH, $enable_path) +dnl +dnl +dnl +dnl Specify what kind of shell we are to build. Options are ksh and sh. +dnl This must be before most other options, as it controls their default +dnl behaviour. +dnl +AC_ARG_ENABLE(shell, +[ --enable-shell={sh,ksh} Specify the kind of shell that is to be built (the + default is ksh). Specifiying sh compiles out: + command line editing (emacs/vi), history, + a bunch of aliases, [[ .. ]], select, let, + brace-expansion, extended globing (*(..|..), etc.), + co-processes, some special environment variables + (ie, MAIL, MAILCHECK, MAILPATH, RANDOM, SECONDS, + TMOUT).],, + enable_shell=ksh) +case $enable_shell in + ksh) AC_DEFINE(KSH) ;; + sh) ;; + *) + AC_MSG_ERROR(bad --enable-shell: must be one of sh or ksh) +esac +SHELL_PROG=$enable_shell +AC_SUBST(SHELL_PROG) +dnl +dnl +dnl +AC_ARG_ENABLE(emacs, +[ --disable-emacs Compile out emacs command line editing (by default, + this is compiled in for ksh, compiled out for sh).]) +case $enable_emacs:$enable_shell in + yes:*|:ksh) enable_emacs=yes; AC_DEFINE(EMACS) ;; + no:*|:sh) enable_emacs=no;; + *) AC_MSG_ERROR(bad --enable-emacs argument) +esac +dnl +dnl +AC_ARG_ENABLE(vi, +[ --disable-vi Compile out vi command line editing (by default, + this is compiled in for ksh, compiled out for sh).]) +case $enable_vi:$enable_shell in + yes:*|:ksh) enable_vi=yes; AC_DEFINE(VI) ;; + no:*|:sh) enable_vi=no;; + *) AC_MSG_ERROR(bad --enable-vi argument) +esac +dnl +dnl +AC_ARG_ENABLE(jobs, +[ --disable-jobs Compile out job control support. If your system + doesn't support job control, this will automatically + be compiled out.]) +case $enable_jobs in + yes|'') enable_jobs=yes; AC_DEFINE(JOBS) ;; + no) enable_jobs=no;; + *) AC_MSG_ERROR(bad --enable-jobs argument) +esac +dnl +dnl +AC_ARG_ENABLE(brace-expand, +[ --disable-brace-expand Compile out brace expansion code (a{b,c} -> ab ac) + (by default, this is compiled in for ksh, compiled + out for sh). Brace expansion can also be disabled + at run time (see set +o braceexpand).]) +case $enable_brace_expand:$enable_shell in + yes:*|:ksh) enable_brace_expand=yes; AC_DEFINE(BRACE_EXPAND) ;; + no:*|:sh) enable_brace_expand=no;; + *) AC_MSG_ERROR(bad --enable-brace-expand argument) +esac +dnl +dnl +AC_ARG_ENABLE(history, +[ --enable-history={no,simple,complex} By default, simple history is used for + ksh, no history is used for sh. \`simple' means + history file is read on start-up, written when shell + exists. \`complex' means history files are updated + after each command so concurrent shells read each + other's commands. Note: \`complex' history doesn't + work well across NFS; also, it requires the mmap() + and flock() functions - if these aren't available, + \`simple' history is automatically used.]) +case $enable_history:$enable_shell in + simple:*|:ksh) enable_history=simple; ;; + complex:*) enable_history=complex; AC_DEFINE(COMPLEX_HISTORY) ;; + no:*|:sh) + case $enable_history:$enable_vi:$enable_emacs in + no:yes:*|no:*:yes) + AC_MSG_ERROR(can't disable history when vi or emacs is enabled) ;; + :yes:*|:*:yes) + enable_history=yes;; + *) + enable_history=no;; + esac + ;; + *) AC_MSG_ERROR(bad --enable-history argument) +esac +test X"$enable_history" != Xno && AC_DEFINE(HISTORY) +dnl +dnl +AC_ARG_ENABLE(posixly_correct, +[ --enable-posixly-correct Enable if you want POSIX behavior by default + (otherwise, posix behavior is only turned on if the + environment variable POSIXLY_CORRECT is present or by + using \"set -o posix\"; it can be turned off with + \"set +o posix\"). See the POSIX Mode section in the + man page for details on what this option affects. + NOTE: posix mode is not compatable with some bourne + sh/at&t ksh scripts.]) +case $enable_posixly_correct:$enable_shell in + yes:*) enable_posixly_correct=yes; AC_DEFINE(POSIXLY_CORRECT) ;; + no:*|:*) enable_posixly_correct=no;; + *) AC_MSG_ERROR(bad --enable-posixly_correct argument) +esac +dnl +dnl +AC_ARG_ENABLE(default-env, +[ --enable-default-env=FILE Include FILE if ENV parameter is not set when + the shell starts. This can be useful when used with + rsh(1), which creates a non-login shell (ie, profile + isn't read, so there is no opertunity to set ENV). + Setting ENV to null disables the inclusion of + DEFAULT_ENV. NOTE: This is a non-standard feature + (ie, at&t ksh has no default environment).],, + enable_default_env=no) +if test X"$enable_default_env" != Xno; then + # The [a-zA-Z]:/ is for os2 types... + case $enable_default_env in + /*|[[a-zA-Z]]:/*) + enable_default_env="\"$enable_default_env\"" + ;; + \"/*\"|\"[[a-zA-Z]]:/*\") + ;; + *) + AC_MSG_ERROR(--enable-default-env argument must be an absolute path (was $enable_default_env)) + ;; + esac + AC_DEFINE_UNQUOTED(DEFAULT_ENV, $enable_default_env) +fi +dnl +dnl +dnl Don't want silly documented - its silly +AC_ARG_ENABLE(silly,[ --enable-silly [A silly option]]) +case $enable_silly:$enable_shell in + yes:*) enable_silly=yes; AC_DEFINE(SILLY) ;; + no:*|:*) enable_silly=no;; + *) AC_MSG_ERROR(bad --enable-silly argument) +esac +dnl +dnl +dnl don't want swtch documented - its ancient and probably doesn't work +AC_ARG_ENABLE(swtch, +[ --enable-swtch For use with shell layers (shl(1)). This has not + been tested for some time.]) +case $enable_swtch:$enable_shell in + yes:*) enable_swtch=yes; AC_DEFINE(SWTCH) ;; + no:*|:*) enable_swtch=no;; + *) AC_MSG_ERROR(bad --enable-swtch argument) +esac +dnl +dnl +dnl Start of auto-configuration stuff... +dnl +dnl +AC_PROG_CC +AC_PROG_CPP +AC_PROG_GCC_TRADITIONAL +dnl A hack to turn on warning messages for gcc - Warn-flags is not in +dnl the distribution since not everyone wants to see this stuff. +dnl (Warn-flags contains: -Wall) +if test X"$GCC" = Xyes && test -f $srcdir/Warn-flags; then + CFLAGS="${CFLAGS+$CFLAGS }`cat $srcdir/Warn-flags`" +fi + +dnl +dnl If LDSTATIC set in environment, pass it on to the Makefile and use it when +dnl doing compile checks to ensure we are checking the right thing. +AC_SUBST(LDSTATIC)LDSTATIC=${LDSTATIC-} +test X"$LDSTATIC" != X && LDFLAGS="${LDFLAGS+$LDFLAGS }$LDSTATIC" +dnl +dnl Executable suffix - normally empty; .exe on os2. +AC_SUBST(ac_exe_suffix)dnl + +dnl this incorperates AC_AIX, AC_ISC_POSIX and AC_MINIX tests and does others +KSH_OS_TYPE +dnl +dnl Program name munging stuff (prefix, suffix, transform) +AC_ARG_PROGRAM +dnl +dnl +dnl Headers +dnl +AC_HEADER_DIRENT +KSH_UNISTD_H +KSH_TERM_CHECK +AC_CHECK_HEADERS(stddef.h stdlib.h string.h memory.h fcntl.h limits.h paths.h \ + sys/param.h sys/resource.h values.h ulimit.h sys/time.h) +AC_HEADER_TIME +KSH_HEADER_SYS_WAIT +dnl +dnl +dnl Typedefs +dnl +dnl (don't use AC_TYPE_XXX() 'cause it doesn't check word boundaries) +KSH_CHECK_H_TYPE(off_t, for off_t in sys/types.h, , long) +KSH_CHECK_H_TYPE(mode_t, for mode_t in sys/types.h, , short) +KSH_CHECK_H_TYPE(pid_t, for pid_t in sys/types.h, , int) +KSH_CHECK_H_TYPE(uid_t, for uid_t in sys/types.h, , int) +if test $ac_cv_type_uid_t = no; then + AC_DEFINE(gid_t, int) +fi +define([AC_PROVIDE_AC_TYPE_UID_T],) +AC_TYPE_SIGNAL +case $ac_cv_type_signal in +int) ksh_cv_signal_retval=0 ;; +void) ksh_cv_signal_retval= ;; +*) + AC_MSG_ERROR(Internal erorr: unknown signal return type: $ac_cv_type_signal) +esac +AC_DEFINE_UNQUOTED(RETSIGVAL, $ksh_cv_signal_retval) +AC_CHECK_SIZEOF(int) +AC_CHECK_SIZEOF(long) +dnl sh.h sets INT32 to int or long as appropriate. Some burnt systems, such +dnl as NeXT's, clock_t is in sys/time.h (in non-posix mode). +KSH_CHECK_H_TYPE(clock_t, [[for clock_t in any of , and ]], + [ +#ifdef HAVE_SYS_TIME_H +#include +#endif /* HAVE_SYS_TIME_H */ +#include + ], INT32) +KSH_CHECK_H_TYPE(sigset_t, for sigset_t in and , + [#include ], unsigned) +KSH_RLIM_CHECK +dnl +dnl +dnl Library functions +dnl +KSH_MEMMOVE +KSH_MEMSET +AC_CHECK_FUNCS(confstr dup2 flock getcwd getwd killpg nice \ + setrlimit strerror strcasecmp strstr sysconf tcsetpgrp \ + ulimit waitpid wait3) +AC_CHECK_FUNCS(sigsetjmp _setjmp, break) +AC_FUNC_MMAP +KSH_FUNC_LSTAT +KSH_SYS_ERRLIST +KSH_SYS_SIGLIST +KSH_TIME_DECLARED +KSH_TIMES_CHECK +dnl +dnl +dnl Structures +dnl +AC_HEADER_STAT +AC_STRUCT_ST_RDEV +dnl +dnl +dnl Compiler characteristics +dnl +AC_C_CONST +KSH_C_VOID +KSH_C_VOLATILE +KSH_C_PROTOTYPES +KSH_C_FUNC_ATTR +dnl +dnl +dnl System services +dnl +AC_SYS_INTERPRETER +if test $ac_cv_sys_interpreter = no; + then AC_DEFINE(SHARPBANG) +fi +AC_PROG_INSTALL +dnl +dnl +dnl Misc ksh tests +dnl +KSH_DUP2_CLEXEC_CHECK +KSH_SIGNAL_CHECK +KSH_PGRP_CHECK +KSH_PGRP_SYNC +KSH_OPENDIR_CHECK +KSH_DEV_FD +dnl +dnl +dnl Take replace value of LDSTATIC in LDFLAGS with reference to make variable +if test X"$LDSTATIC" != X; then + LDFLAGS=`echo -- "$LDFLAGS" | sed -e 's/^-- //' -e 's?$LDSTATIC?\$(LDSTATIC)?'` +fi +dnl +AC_OUTPUT(Makefile) diff --git a/etc/ksh.kshrc b/etc/ksh.kshrc new file mode 100644 index 0000000..f551145 --- /dev/null +++ b/etc/ksh.kshrc @@ -0,0 +1,209 @@ +: +# NAME: +# ksh.kshrc - global initialization for ksh +# +# DESCRIPTION: +# Each invocation of /bin/ksh processes the file pointed +# to by $ENV (usually $HOME/.kshrc). +# This file is intended as a global .kshrc file for the +# Korn shell. A user's $HOME/.kshrc file simply requires +# the line: +# . /etc/ksh.kshrc +# at or near the start to pick up the defaults in this +# file which can then be overridden as desired. +# +# SEE ALSO: +# $HOME/.kshrc +# + +# RCSid: +# $Id: ksh.kshrc,v 1.1 2004/03/21 00:34:32 tg Exp $ +# +# @(#)Copyright (c) 1991 Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. + +case "$-" in +*i*) # we are interactive + # we may have su'ed so reset these + # NOTE: SCO-UNIX doesn't have whoami, + # install whoami.sh + USER=`whoami 2>/dev/null` + USER=${USER:-`id | sed 's/^[^(]*(\([^)]*\)).*/\1/'`} + case $UID in + 0) PS1S='# ';; + esac + PS1S=${PS1S:-'$ '} + HOSTNAME=${HOSTNAME:-`uname -n`} + HOST=${HOSTNAME%%.*} + + PROMPT="$USER:!$PS1S" + #PROMPT="<$USER@$HOST:!>$PS1S" + PPROMPT='$USER:$PWD:!'"$PS1S" + #PPROMPT='<$USER@$HOST:$PWD:!>'"$PS1S" + PS1=$PPROMPT + # $TTY is the tty we logged in on, + # $tty is that which we are in now (might by pty) + tty=`tty` + tty=`basename $tty` + TTY=${TTY:-$tty} + + set -o emacs + + alias ls='ls -CF' + alias h='fc -l | more' + _cd() { "cd" $*; } + # the PD ksh is not 100% compatible + case "$KSH_VERSION" in + *PD*) # PD ksh + case "$TERM" in + pc3|xterm*) + # bind arrow keys + bind '^[['=prefix-2 + bind '^XA'=up-history + bind '^XB'=down-history + bind '^XC'=forward-char + bind '^XD'=backward-char + ;; + esac + ;; + *) # real ksh ? + [ -r $HOME/.functions ] && . $HOME/.functions + set -o trackall + ;; + esac + case "$TERM" in + sun*) + # these are not as neat as their csh equivalents + if [ "$tty" != console ]; then + # ilabel + ILS='\033]L'; ILE='\033\\' + # window title bar + WLS='\033]l'; WLE='\033\\' + fi + ;; + xterm*) + ILS='\033]1;'; ILE='\007' + WLS='\033]2;'; WLE='\007' + parent="`ps -ax 2>/dev/null | grep $PPID | grep -v grep`" + case "$parent" in + *telnet*) + export TERM=xterms;; + esac + ;; + *) ;; + esac + # do we want window decorations? + if [ "$ILS" ]; then + ilabel () { print -n "${ILS}$*${ILE}"; } + label () { print -n "${WLS}$*${WLE}"; } + + alias stripe='label "$USER@$HOST ($tty) - $PWD"' + alias istripe='ilabel "$USER@$HOST ($tty)"' + + wftp () { ilabel "ftp $*"; "ftp" $*; eval istripe; } + wcd () { _cd $*; eval stripe; } + wtelnet () + { + "telnet" "$@" + eval istripe + eval stripe + } + wrlogin () + { + "rlogin" "$@" + eval istripe + eval stripe + } + wsu () + { + "su" "$@" + eval istripe + eval stripe + } + alias su=wsu + alias cd=wcd + alias ftp=wftp + alias telnet=wtelnet + alias rlogin=wrlogin + eval stripe + eval istripe + PS1=$PROMPT + fi + alias quit=exit + alias cls=clear + alias logout=exit + alias bye=exit + alias p='ps -l' + alias j=jobs + alias o='fg %-' + alias ls='ls -gCF' + +# add your favourite aliases here + OS=${OS:-`uname -s`} + case $OS in + HP-UX) + alias ls='ls -CF' + ;; + *BSD) + alias df='df -k' + alias du='du -k' + ;; + esac + alias rsize='eval `/usr/bin/X11/resize`' + + case "$TERM" in + sun*|xterm*) + case $tty in + tty[p-w]*) + case "$DISPLAY" in + "") + DISPLAY="`who | grep $TTY | sed -n 's/.*(\([^:)]*\)[:)].*/\1/p' | sed 's/\([a-zA-Z][^.]*\).*/\1/'`:0" + ;; + esac + ;; + esac + case "$DISPLAY" in + ozen*|:*) + stty erase "^?" + ;; + *) + stty erase "^h" + ;; + esac + export DISPLAY + ;; + esac + +;; +*) # non-interactive +;; +esac +# commands for both interactive and non-interactive shells + +# is $1 missing from $2 (or PATH) ? +no_path () { + eval _v="\$${2:-PATH}" + case :$_v: in + *:$1:*) return 1;; # no we have it + esac + return 0 +} +# if $1 exists and is not in path, append it +add_path () { + [ -d ${1:-.} ] && no_path $* && eval ${2:-PATH}="\$${2:-PATH}:$1" +} +# if $1 exists and is not in path, prepend it +pre_path () { + [ -d ${1:-.} ] && no_path $* && eval ${2:-PATH}="$1:\$${2:-PATH}" +} +# if $1 is in path, remove it +del_path () { + no_path $* || eval ${2:-PATH}=`eval echo :'$'${2:-PATH}: | + sed -e "s;:$1:;:;g" -e "s;^:;;" -e "s;:\$;;"` +} diff --git a/etc/profile b/etc/profile new file mode 100644 index 0000000..8e7705b --- /dev/null +++ b/etc/profile @@ -0,0 +1,310 @@ +: +# NAME: +# profile - global initialization for sh,ksh +# +# DESCRIPTION: +# This file is processed during login by /bin/sh +# and /bin/ksh. It is used to setup the default user +# environment. +# +# SEE ALSO: +# $HOME/.profile +# /etc/ksh.kshrc + +# RCSid: +# $Id: profile,v 1.1 2004/03/21 00:34:32 tg Exp $ +# +# @(#)Copyright (c) 1991 Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. + +sigs="2 3" +trap "" $sigs # don't interrupt us + +# simple versions. See ksh.kshrc for the clever ones +add_path () { [ -d $1 ] && eval ${2:-PATH}="\$${2:-PATH}:$1"; } +pre_path () { [ -d $1 ] && eval ${2:-PATH}="$1:\$${2:-PATH}"; } +del_path () { eval ${2:-PATH}=`eval echo :'$'${2:-PATH}: | + sed -e "s;:$1:;:;g" -e "s;^:;;" -e "s;:\$;;"`; } + +case "$_INIT_" in +*env*) ;; +*) # do these once + _INIT_="$_INIT_"env + export _INIT_ + case `echo -n ""` in + -n*) + N=""; C="\c";; + *) + N="-n"; C="";; + esac + + if [ -f /unix ]; then + # System V + [ -z "$TZ" -a -f /etc/TIMEZONE ] && . /etc/TIMEZONE + + set -- `who -r` + case "$3" in + S|5|0) SINGLE=y;; + *) SINGLE=n;; + esac + else + SINGLE=n # doesn't matter so much + fi + + OS=${OS:-`uname -s`} + ARCH=${ARCH:-`uname -m`} + HOSTNAME=`hostname 2>/dev/null` + HOSTNAME=${HOSTNAME:-`uname -n`} + export OS ARCH HOSTNAME + + # pick one of the following for the default umask + umask 002 # relaxed -rwxrwxr-x + # umask 022 # cautious -rwxr-xr-x + # umask 027 # uptight -rwxr-x--- + # umask 077 # paranoid -rwx------ + # you can override the default umask + # for specific groups later... + + if [ -d /local ]; then + LOCAL=/local + else + LOCAL=/usr/local + fi + + # defaults (might be reset below) + PATH=/bin:/usr/bin + MANPATH=/usr/man + SPOOL=/usr/spool + defterm=vt220 + + # set system specific things, + # eg. set PATH,MANPATH + # override default ulimit if desired. + # defult ulmit is unlimited on SunOS + # and 4Mb for most System V + case $OS in + SunOS) + # On sun's /bin -> /usr/bin so leave it out! + PATH=/usr/bin:/usr/ucb:/usr/5bin:/usr/etc + SPOOL=/var/spool + LD_LIBRARY_PATH=/usr/lib + add_path /usr/snm/lib LD_LIBRARY_PATH + add_path /usr/X11R5/lib LD_LIBRARY_PATH + add_path /usr/openwin/lib LD_LIBRARY_PATH + export LD_LIBRARY_PATH + ;; + SCO-UNIX) + defterm=ansi + ;; + B.O.S.) + MANPATH=/usr/catman + SRC_COMPAT=_SYSV + export SRC_COMPAT + ;; + NetBSD|386bsd) + MACHINE_ARCH=`uname -m` + MANPATH=/usr/share/man + add_path /usr/X386/man MANPATH + MAILDIR=/var/mail + SPOOL=/var/spool + export MACHINE_ARCH + ;; + esac + # add_path only adds them if they exist + add_path /sbin + add_path /usr/sbin + add_path /usr/distbin + add_path /usr/ucb + add_path /usr/lbin + add_path /usr/dbin + add_path /usr/ldbin + add_path ${LOCAL}/bin + add_path /usr/bin/X11 + add_path /usr/X11R5/bin + add_path /usr/openwin/bin + # ensure . is at end + PATH=$PATH:. + + case "$HOME" in + /) ;; + ""|/tmp) + echo "Using /tmp for HOME" + HOME=/tmp; export HOME + ;; + *) + pre_path $HOME/bin + ;; + esac + add_path /usr/X11R5/man MANPATH + add_path ${LOCAL}/man MANPATH + + # make sure these are set at least once + LOGNAME=${LOGNAME:-`logname`} + USER=${USER:-$LOGNAME} + + # NOTE: set up $GROUPDIR such that users cannot modify/install + # their own $GROUPDIR/profile + GROUPDIR=`dirname $HOME` + [ "$GROUPDIR" != /etc -a -f $GROUPDIR/profile ] && . $GROUPDIR/profile + + export LOCAL TTY PATH LOGNAME USER + + if [ -t 1 ]; then + # we are interactive + TTY=`tty` + TTY=`basename $TTY` + if [ -f /etc/organization ]; then + ORGANIZATION="`cat /etc/organization`" + COPYRIGHT="Copyright (c) `date +19%y` $ORGANIZATION" + export ORGANIZATION COPYRIGHT + fi + # set up some env variables + MAIL=${MAILDIR:-$SPOOL/mail}/$USER + MAILPATH=$MAIL:/etc/motd + EMACSDIR=${LOCAL}/lib/emacs + PAGER=${PAGER:-more} + export MAIL EMACSDIR MANPATH MAILPATH PAGER + + CVSROOT=${LOCAL}/src/master + EDITOR=vi + VISUAL=vi + FCEDIT=$EDITOR + export CVSROOT FCEDIT EDITOR VISUAL + case $UID in + 0) PS1S='# ';; + esac + PS1S=${PS1S:-'$ '} + PROMPT="<$LOGNAME@$HOSTNAME>$PS1S" + [ -f /etc/profile.TeX ] && . /etc/profile.TeX + else + TTY=none + fi + + # test (and setup if we are Korn shell) + if [ "$RANDOM" != "$RANDOM" ]; then + # we are Korn shell + SHELL=/bin/ksh + ENV=${HOME%/}/.kshrc + if [ ! -f $ENV ]; then + ENV=/etc/ksh.kshrc + fi + HISTFILE=${HOME%/}/.ksh_hist + PROMPT="<$LOGNAME@$HOSTNAME:!>$PS1S" + export HISTSIZE HISTFILE ENV + CDPATH=.:$HOME + if [ "$TMOUT" ]; then + typeset -r TMOUT + fi + set -o emacs # biased :-) + else + SHELL=/bin/sh + fi + PS1=$PROMPT + export SHELL PS1 EDITOR PATH PROMPT HOSTNAME CDPATH +;; +esac + +# login time initialization +case "$_INIT_" in +*log*) ;; +*) _INIT_="$_INIT_"log + case "$SINGLE" in + y) ;; + *) + if [ TTY != none -a "$0" != "-su" -a "$LOGNAME" = "`logname`" ] + then + case $TTY in + tty0*) + echo "`date '+%b %d %H:%M:%S'` $LOGNAME logged in on $TTY" > /dev/console;; + esac + stty sane # usually a good idea :-) + if [ ! -f ~/.hushlogin ]; then + # ensure known state + case $OS in + SunOS|*BSD) ;; + *) + stty isig icanon intr '^c' erase '^h' kill '^u' eof '^d' + mesg y + ;; + esac + + case $TERM in + network|unknown|dialup|"") + echo ${N} "Enter terminal type [$defterm]: ${C}" 1>&2 + read tmpterm + TERM=${tmpterm:-$defterm} + ;; + esac + case "$TERM" in + pc3|xterm) + stty erase ^? + ;; + esac + # not all of the following are appropriate at all sites + # Sun's don't need to cat /etc/motd for instance + case "$OS" in + SunOS) ;; + SCO-UNIX) + [ -s /etc/motd ] && cat /etc/motd + [ -x /usr/bin/mail -a -s "$MAIL" ] && + echo "You have mail." + [ -x /usr/bin/news ] && /usr/bin/news -n + ;; + NetBSD|386bsd) + # hardware flow control works so use it + case $TTY in + tty0*) # dialups + stty -ixon -ixany + stty crtscts + ;; + esac + ;; + *) + [ -s /etc/motd ] && cat /etc/motd + if [ -x /usr/bin/mailx ]; then + if mailx -e; then + echo "You have mail." + # show the the headers, this might + # be better done in .profile so they + # can override it. +# mailx -H + fi + fi + [ -x /usr/bin/news ] && /usr/bin/news -n + ;; + esac + if [ -f $LOCAL/etc/1stlogin.ann ]; then + [ -f $HOME/... ] || sh $LOCAL/etc/1stlogin.ann + fi +# [ -x /usr/games/fortune ] && /usr/games/fortune -a + # remind folk who turned on reply.pl to turn it off. + if [ -f $HOME/.forward ]; then + echo "Your mail is being forwarded to:" + cat $HOME/.forward + if [ -f $HOME/.recording ]; then + echo "Perhaps you should run \"reply.pl off\"" + fi + fi + [ -x /usr/ucb/msgs ] && /usr/ucb/msgs -fq + fi + fi + unset tmpterm defterm C N + esac + case "$TERM" in + network|unknown|"") TERM=$defterm;; + esac + export TERM TTY +;; +esac +# Handle X-terminals if necessary +[ "$SINGLE" = n -a -f /etc/profile.X11 ] && . /etc/profile.X11 + +# make sure you have this bit last +trap $sigs # restore signals +unset sigs diff --git a/etc/sys_config.sh b/etc/sys_config.sh new file mode 100644 index 0000000..dd3409c --- /dev/null +++ b/etc/sys_config.sh @@ -0,0 +1,64 @@ +: +# NAME: +# sys_config.sh - set system specific variables +# +# SYNOPSIS: +# . /etc/sys_config.sh +# +# DESCRIPTION: +# Source this script into shell scripts that want to handle +# various system types. +# You may well want to edit this on a particular system replacing +# `uname -s` etc with the result. So that the facility will work +# even when in single user mode and uname et al are not available. +# +# SEE ALSO: +# /etc/profile + +# RCSid: +# $Id: sys_config.sh,v 1.1 2004/03/21 00:34:32 tg Exp $ +# +# @(#)Copyright (c) 1991 Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# + +# determin machine type +if [ -f /386bsd ]; then # doesn't have uname or arch + ARCH=i386 + OS=386bsd + HOSTNAME=`hostname` +elif [ -f /usr/bin/arch ]; then + ARCH=`arch` +elif [ -f /usr/bin/uname -o -f /bin/uname ]; then + ARCH=`uname -m` +fi +# +case "$ARCH" in +sun386) uname=/usr/5bin/uname + OS=SunOS + ;; +*) uname=uname;; +esac + +# set the operating system type +# you can't use `uname -s` with SCO UNIX +# it returns the same string as `uname -n` +# so set it manually +# OS=SCO-UNIX +# The eval below is a workaround for a bug in the PD ksh. +OS=${OS:-`eval $uname -s`} +HOSTNAME=${HOSTNAME:-`eval $uname -n`} + +case `echo -n ""` in +-n*) _C_=""; _N_="-n";; +*) _C_="\c"; _N_="";; +esac +N="${_N_}" +C="${_C_}" +export OS ARCH HOSTNAME uname diff --git a/install-sh b/install-sh new file mode 100644 index 0000000..0ff4b6a --- /dev/null +++ b/install-sh @@ -0,0 +1,119 @@ +#!/bin/sh + +# +# install - install a program, script, or datafile +# This comes from X11R5; it is not part of GNU. +# +# $XConsortium: install.sh,v 1.2 89/12/18 14:47:22 jim Exp $ +# +# This script is compatible with the BSD install script, but was written +# from scratch. +# + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" + +instcmd="$mvprog" +chmodcmd="" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +fi + +if [ x"$dst" = x ] +then + echo "install: no destination specified" + exit 1 +fi + + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + +if [ -d $dst ] +then + dst="$dst"/`basename $src` +fi + +# Make a temp file name in the proper directory. + +dstdir=`dirname $dst` +dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + +$doit $instcmd $src $dsttmp + +# and set any options; do chmod last to preserve setuid bits + +if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; fi +if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; fi +if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; fi +if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; fi + +# Now rename the file to the real destination. + +$doit $rmcmd $dst +$doit $mvcmd $dsttmp $dst + + +exit 0 diff --git a/ksh.Man b/ksh.Man new file mode 100644 index 0000000..f858ba3 --- /dev/null +++ b/ksh.Man @@ -0,0 +1,3532 @@ +'\" t +.\"{{{}}} +.\"{{{ 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 +.ksh( +.TH KSH 1 "August 19, 1996" "" "User commands" +.ksh) +.sh( +.TH SH 1 "August 19, 1996" "" "User commands" +.sh) +.\"}}} +.\"{{{ Name +.SH NAME +.ksh( +ksh \- Public domain Korn shell +.ksh) +.sh( +sh \- Public domain Bourne shell +.sh) +.\"}}} +.\"{{{ Synopsis +.SH SYNOPSIS +.ad l +.ksh( +\fBksh\fP +.ksh) +.sh( +\fBsh\fP +.sh) +[\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 +.ksh( +\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. +.ksh) +.sh( +\fBsh\fP is a reimplementation of the Bourne shell, a command +interpreter for both interactive and script use. +.sh) +.\"{{{ 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; +.ksh( +\fB|&\fP is used to create co-processes (see Co-Processes below); +.ksh) +\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; +.ksh( +\fB((\fP .. \fB))\fP are used in arithmetic expressions; +.ksh) +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). +.ksh( +The \fB|&\fP operator starts a \fIco-process\fP which is special kind of +asynchronous process (see Co-Processes below). +.ksh) +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}\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 +.ksh( +.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. +.ksh) +.\"}}} +.\"{{{ 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. +.\"}}} +.\"{{{ time [-p] [ pipeline ] +.IP "\fBtime\fP [ \fB-p\fP ] [ \fIpipeline\fP ]" +The \fBtime\fP reserved word is described in the Command Execution section. +.\"}}} +.\"{{{ (( expression )) +.ksh( +.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. +.ksh) +.\"}}} +.\"{{{ [[ expression ]] +.ksh( +.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 +.ksh) +.\"}}} +.\"}}} +.\"}}} +.\"{{{ 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 +.ksh( +autoload='typeset \-fu' +.br +functions='typeset \-f' +.br +.ksh) +hash='alias \-t' +.ksh( +.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 $$' +.ksh) +.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 `:', the sequence of characters +`A: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). +The later form can be treated as arrays by appending an array +index of the form: \fB[\fP\fIexpr\fP\fB]\fP where \fIexpr\fP is +an arithmetic expression. +Array indicies are currently limited to the range 0 through 1023, inclusive. +Parameter substitutions take the form \fB$\fP\fIname\fP, +\fB${\fP\fIname\fP\fB}\fP or +\fB${\fP\fIname\fP\fB[\fP\fIexpr\fP\fB]}\fP, where \fIname\fP is a +parameter name. +If substitution is performed on a parameter (or an array parameter element) +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: +.\"{{{ _ +.ksh( +.IP "\fB_\fP \fI(underscore)\fP" +When an external command is executed by the shell, this parameter is +set in the environment of the new process to the path of the executed +command. +In interactive use, this parameter is also set in the parent shell to +the last word of the previous command. +When \fBMAILPATH\fP messages are evaluated, this parameter contains +the name of the file that changed (see \fBMAILPATH\fP parameter below). +.ksh) +.\"}}} +.\"{{{ 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 +.ksh( +.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. +.ksh) +.\"}}} +.\"{{{ 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 +.ksh( +.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. +.ksh) +.\"}}} +.\"{{{ HISTSIZE +.ksh( +.IP \fBHISTSIZE\fP +The number of commands normally stored for history, default 128. +.ksh) +.\"}}} +.\"{{{ 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 +.ksh( +.IP \fBKSH_VERSION\fP +The version of shell and the date the version was created (readonly). +See also the version commands in Emacs Editing Mode +and Vi Editing Mode sections, below. +.ksh) +.\"}}} +.\"{{{ SH_VERSION +.sh( +.IP \fBSH_VERSION\fP +The version of shell and the date the version was created (readonly). +.sh) +.\"}}} +.\"{{{ LINENO +.IP \fBLINENO\fP +The line number of the function or shell script that is currently being +executed. +.\"}}} +.\"{{{ 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 +.ksh( +.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. +.ksh) +.\"}}} +.\"{{{ MAILCHECK +.ksh( +.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). +.ksh) +.\"}}} +.\"{{{ MAILPATH +.ksh( +.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. +.ksh) +.\"}}} +.\"{{{ 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. +.ksh( +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. +.ksh) +.sh( +The prompt is printed verbatim (\fIi.e.\fP, no substitutions are done). +.sh) +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 +.ksh( +.IP \fBPS3\fP +Prompt used by \fBselect\fP statement when reading a menu selection. +Default is `\fB#?\ \fP'. +.ksh) +.\"}}} +.\"{{{ PS4 +.IP \fBPS4\fP +Used to prefix commands that are printed during execution tracing +(see \fBset \-x\fP command below). +.ksh( +Parameter, command and arithmetic substitutions are performed +before it is printed. +.ksh) +.sh( +The prompt is printed verbatim (\fIi.e.\fP, no substitutions are done). +.sh) +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 +.ksh( +.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)). +.ksh) +.\"}}} +.\"{{{ 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 +.ksh( +.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. +.ksh) +.\"}}} +.\"{{{ TMOUT +.ksh( +.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. +.ksh) +.\"}}} +.\"{{{ 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 +.ksh( +.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. +.ksh) +.\"}}} +.\"}}} +.\"}}} +.\"{{{ 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 +.ksh( +.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. +.ksh) +.\"}}} +.\"{{{ 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. +.ksh( +.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). +.ksh) +.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 +(if the shell is interactive) 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 +.ksh( +with the \fBlet\fP command, +.ksh) +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" +separates 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 \fP\fB=\fP \fI\fP is the same as +\fI\fP \fB=\fP \fI \fP \fB(\fP \fI\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\fP \fB?\fP \fI\fP \fB:\fP \fI\fP" +if \fI\fP is non-zero, the result is \fI\fP, +otherwise \fI\fP. +.RE +.\"}}} +.\"{{{ Co-Processes +.ksh( +.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 +.ksh) +.\"}}} +.\"{{{ 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). +.IP \ \ \(bu +\fBOPTIND\fP is saved/reset and restored on entry and exit from the function +so \fBgetopts\fP can be used properly both inside and outside the function +(Bourne-style functions leave \fBOPTIND\fP untouched, so using \fBgetopts\fP +inside a function interferes with using \fBgetopts\fP outside the function). +.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 +.sh( +.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. +.sh) +.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 +\fBeval\fP exit status: if eval gets to see an empty command (\fIe.g.\fP, +\fBeval "`false`"\fP), its exit status in posix mode will be 0. +In non-posix mode, it will be the exit status of the last +command substitution that was done in the processing of the arguments to eval +(or 0 if there were no command substitutions). +.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. +.IP \ \ \(bu +test: in posix mode, the expression "\fB-t\fP" (preceded by +some number of "\fB!\fP" arguments) is always true as it is a non-zero length +string; in non-posix mode, it tests if file descriptor 1 is a tty (\fIi.e.\fP, +the \fIfd\fP argument to the \fB-t\fP test may be left out and defaults to 1). +.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 ] ] [+-px] [+-] [name1[=value1] ...] +.IP "\fBalias\fP [ \fB\-d\fP | \fB\(+-t\fP [\fB\-r\fP] ] [\fB\(+-px\fP] [\fB\(+-\fP] [\fIname1\fP[\fB=\fP\fIvalue1\fP] ...]" +Without arguments, \fBalias\fP lists all aliases. +For any name without a value, the existing alias is listed. +Any name with a value defines an alias (see Aliases above). +.sp +When listing aliases, one of two formats is used: +normally, aliases are listed as \fIname\fP\fB=\fP\fIvalue\fP, where +\fIvalue\fP is quoted; if options were preceded with \fB+\fP +or a lone \fB+\fP is given on the command line, only \fIname\fP +is printed. +In addition, if the \fB\-p\fP option is used, each alias +is prefixed with the string "\fBalias\fP\ ". +.sp +The \fB\-x\fP option sets (\fB+x\fP clears) the export attribute of an alias, +or, if no names are given, lists the aliases with the export attribute +(exporting an alias 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 Editing Mode 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 directories to search in for \fIdir\fP. +\fIdir\fP. An empty entry in the \fBCDPATH\fP entry means the current +directory. +If a non-empty directory from \fBCDPATH\fP is used, the resulting full +path is printed to standard output. +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 ...] +.ksh( +.IP "\fBcommand\fP [\fB\-pvV\fP] \fIcmd\fP [\fIarg1\fP ...]" +If neither the \fB\-v\fP nor \fB\-V\fP options are given, +.ksh) +.sh( +.IP "\fBcommand\fP [\fB\-p\fP] \fIcmd\fP [\fIarg1\fP ...]" +.sh) +\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 +.ksh( +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. +.ksh) +.\"}}} +.\"{{{ 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. +.ksh( +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). +Note that the Bourne shell differs here: it does pass these +file descriptors on. +.ksh) +.sh( +Any file descriptors which are opened or \fIdup\fP(2)-ed +in this way are made available to other executed commands +(note that the Korn shell differs here: it does not pass on +file descriptors greater than 2). +.sh) +.\"}}} +.\"{{{ 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 ]] +.ksh( +.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. +.ksh) +.\"}}} +.\"{{{ 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. +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 ...] +.ksh( +.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. +.ksh) +.\"}}} +.\"{{{ 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} +.ksh( + braceexpand T{ +Enable brace expansion (aka, alternation). +T} +.ksh) +.ksh( + emacs T{ +Enable BRL emacs-like command line editing (interactive shells only); +see Emacs Editing Mode. +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} +.ksh) + ignoreeof T{ +The shell will not (easily) exit on when end-of-file is read, \fBexit\fP must +be used. +To avoid infinite loops, the shell will exit if eof is read 13 times in +a row. +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 or first +\fIfile\fP exists and the second \fIfile\fP does not. +T} +\fIfile\fP \-ot \fIfile\fP T{ +first \fIfile\fP is older than second \fIfile\fP or second \fIfile\fP +exists and the first \fIfile\fP does not. +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. +If the posix option (\fBset \-o posix\fP, see POSIX Mode above) is not +set, \fIfd\fP may be left out, in which case it is taken to be 1 +(the behaviour differs due to the special POSIX rules described below). +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} +.ksh( +\fIstring\fP\ ==\ \fIstring\fP T{ +strings are equal. +T} +.ksh) +\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. +.\"}}} +.\"{{{ time [-p] [pipeline] +.IP "\fBtime\fP [\fB-p\fP] [ \fIpipeline\fP ]" +If a pipeline is given, the times used to execute the pipeline are reported. +If no pipeline is given, then the user and system time used by the shell +itself, and all the commands it has run since it was started, are reported. +The times reported are +the real time (elapsed time from start to finish), +the user cpu time (time spent running in user mode) +and the system cpu time (time spent running in kernel mode). +Times are reported to standard error; the format of the output is: +.nf + 0.00s real 0.00s user 0.00s system +.fi +unless the -p option is given (only possible if \fIpipeline\fP is a simple +command), in which case the output is slightly longer: +.nf + real 0.00 + user 0.00 + sys 0.00 +.fi +(the number of digits after the decimal may vary from system to system). +Note that simple redirections of standard error do not effect the output +of the time command: +.ce +\fBtime sleep 1 2> \fP\fIafile\fP +.ce +\fB{ time sleep 1; } 2> \fP\fIafile\fP +times for the first command do not go to \fIafile\fP, but those of the +second command do. +.\"}}} +.\"{{{ 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. +Note that the output of \fBtrap\fP can not be usefully piped to another process +(an artifact of the fact that traps are cleared when subprocesses are +created). +.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 [[+-Ulprtux] [-L[n]] [-R[n]] [-Z[n]] [-i[n]] | -f [-tux]] [name[=value] ...] +.IP "\fBtypeset\fP [[\(+-Ulprtux] [\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} +\-p T{ +Print complete typeset commands that can be used to re-create the +attributes (but not the values) of parameters. +This is the default action (option exists for ksh93 compatability). +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. +.\"}}} +.\"{{{ Interactive Input Line Editing +.ksh( +.\"{{{ introduction +.SS "Interactive Input Line Editing" +The shell supports three modes of reading command lines from a tty +in an interactive session. +Which is used is controlled by the \fBemacs\fP, \fBgmacs\fP and \fBvi\fP +\fBset\fP options (at most one of these can be set at once). +If none of these options is enabled, the shell simply reads lines +using the normal tty driver. +If the \fBemacs\fP or \fBgmacs\fP option is set, the shell allows +emacs like editing of the command; similarly, if the \fBvi\fP option +is set, the shell allows vi like editing of the command. +These modes are described in detail in the following sections. +.\"}}} +.\"{{{ display +.PP +In these editing modes, 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. +.\"}}} +.\"{{{ Emacs Editing Mode +.SS "Emacs Editing Mode" +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 ^[ +.IP "\fBset-mark-command ^[\fP" +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 Editing Mode +.\"{{{ introduction +.SS "Vi Editing Mode" +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\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\fP, \fB\fP +and \fB\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} + 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} + T{ +optional file name and command completion (see \fB^F\fP above), enabled with +\fBset \-o vi-tabcomplete\fP +T} +.TE +.\"}}} +.\"{{{ 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\fP and \fIn\fP\fB\fP" +command/file name completion: +replace the current big-word with the longest unique +match obtained after performing command/file name expansion. +\fB\fP is only recognized if the \fBvi-tabcomplete\fP option is set, +while \fB\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\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, + 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, + 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 +.\"}}} +.\"}}} +.\"}}} +.ksh) +.\"}}} +.\"}}} +.\"{{{ 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://ftp.cs.mun.ca/pub/pdksh/. +.PP +BTW, the most frequently reported bug is +.RS +\fB echo hi | read a; echo $a\fP\ \ \ # Does not print hi +.RE +I'm aware of this and there is no need to report it. +.\"}}} +.\"{{{ Version +.SH VERSION +This page documents version +.ce + @(#)PD KSH v5.2.14 99/07/13.2 +of the public domain korn shell. +.\"}}} +.\"{{{ 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 +of pdksh 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( +sh(1), +.ksh) +.sh( +ksh(1), +.sh) +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/misc/Bugs b/misc/Bugs new file mode 100644 index 0000000..7a411f8 --- /dev/null +++ b/misc/Bugs @@ -0,0 +1,652 @@ +if [ $# != 1 ] ; then + echo "Usage: ksh-prog Bugs ksh-prog" 1>&2 + exit 1 +fi +THIS_KSH=$1 +shift + +echo 'The following tests are known to fail: + 39' + +tbase=bug-t$$ +tfile=/tmp/$tbase +sfile=/tmp/bug-s$$ + +# 1. Everywhere +# lex array code has problems.... +# $ echo blah[ +# missing ] +# $ +# Different view of same bug: +# $ n=blah echo "hi[ $n ]" +# hi[ $n ] +# $ +n=blah +x=$(echo hi[ $n ]=1) +if [ "$x" = 'hi[ $n ]=1' ] ; then + echo 'Bug 1 present (echo "hi[ $n ] " prints hi[ $n ]).' +fi +unset n x + +# +# 2. Everywhere +# 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. +cat > $tfile << 'EOF' +#!/bin/sh +echo hi +exit 0 +EOF +chmod a+rx $tfile +PATH=/tmp $tbase > /dev/null 2>&1 +if [ $? != 0 ] ; then + echo "Bug 2 present: local assignments to PATH don't effect PATH search" +fi +rm -f $tfile + +# +# 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]" + +# +# 6. Everywhere +# 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... +cat > $tfile << 'EOF' + echo $(echo \() +EOF +out=`$THIS_KSH $tfile 2>&1` +if [ "X$out" != 'X(' ] ; then + echo 'Bug 6 present: can'\''t quote ( inside $(..) escapes' +fi +rm -f $tfile + +# +# 7. (fixed) +# +echo " [Don't know what bug 7 was]" + +# +# 8. Everywhere - NOT A BUG - this is what at&t ksh 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]' + +# +# 9. (fixed) Fix is to make sure Volatile is not defined to nothing +# (see defines in sh.h) +# 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... +first=yes +for i in a b c ; do + if [ $i = b ] ; then + if [ $first = no ] ; then + echo 'Bug 9 present: continue in for loop broken' + break # hope break isn't broken too :-) + fi + first=no + continue + fi +done + +# +# 10. Everywhere +# The following: +# set -- `false` +# echo $? +# shoud not print 0. (according to /bin/sh, at&t ksh, and the +# getopt(1) man page - not according to POSIX) +set -- `false` +if [ $? != 1 ] ; then + echo 'Bug 10 present: set exit code overrides exit code of command subst' +fi + +# +# 11. Some places (sun4s but not mips) +# The following: +# x=/foo/bar/blah +# echo ${x##*/} +# should echo blah but on some machines echos /foo/bar/blah. +x=/foo/bar/blah +if [ ${x##*/} != blah ] ; then + echo 'Bug 11 present: ${x##*/} doesn'\''t work' +fi +unset x + +# +# 12. Everywhere: +# 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) +x="foo bar" +if [ "X`echo \"$x\"`" != "Xfoo bar" ] ; then + echo 'Bug 12 present: quotes inside `` sequences different from sh' +fi +unset x + +# +# 13. Everywhere +# 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. +trap 'echo "Bug 13 present: pipes not closed properly"; trap 2' 2 +echo " [If this hangs for more than a second, hit ^C]" +(: ; cat /etc/termcap) | sleep 1 +trap 2 +echo " [relax, no bug 13]" + + +# +# 14. Everywhere +# 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 ksh produces +# no error (redirected to /dev/null). +cat > $tfile << 'EOF' + (you/should/not/see/this/error/1) 2> /dev/null + you/should/not/see/this/error/2 2> /dev/null +EOF +if $THIS_KSH $tfile 2>&1 | grep you/should > /dev/null; then + echo "Bug 14 present: shell 'command not found' error not redirected" +fi +rm -f $tfile + +# +# 15. Everywhere +# The command +# $ whence foobar +# generates a blank line under pdksh and sets the exit status to 0. +# at&t ksh generates no output and sets the exit status to 1. Also, +# the command +# $ whence foobar cat +# generates no output under at&t ksh (pdksh generates a blank line +# and /bin/cat). +echo " [Note that there are three bug 15 tests: 15a, 15b, 15c]" +cat > $tfile << 'EOF' + whence does/not/exist > /dev/null + echo $? +EOF +out=`$THIS_KSH $tfile 2> /dev/null` +if [ "$out" != 1 ] ; then + echo 'Bug 15a present: exit status of whence wrong' +fi +rm -f $tfile +x=$(whence does/not/exist | wc -l) +case $x in +*0*) ;; +*) echo 'Bug 15b present: whence produces blank lines' +esac +x=$(whence does/not/exist cat | wc -l) +case $x in +*2*) echo 'Bug 15c present: whence continues after error' +esac +unset x + +# +# 16. Everywhere +# ${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... +read x < /etc/passwd +y=$x +echo ${x%%:*} > /dev/null +if [ "$x" != "$y" ] ; then + echo 'Bug 16 present: ${..%%..} trashes variables' +fi +unset x y + +# +# 17. Everywhere +# The command +# . /foo/bar +# should set the exit status to non-zero (sh and at&t ksh do). +# XXX doting a non existant file is a fatal error for a script +cat > $tfile << 'EOF' + (. does/not/exist) + echo $? +EOF +out=`$THIS_KSH $tfile 2> /dev/null` +if [ "$out" != 1 ] ; then + echo 'Bug 17 present: exit status of . wrong' +fi +rm -f $tfile + +# +# 18. Everywhere +# In vi mode ^X (and *) can dump core: +# $ ab[cd^XMemory fault (core dumped) +echo " [No automatic test for bug 18 - interactive]" + +# +# 19. Everywhere +# Both of the following echos should produce the same thing, but don't: +# $ x=foo/bar +# $ echo ${x%/*} +# foo +# $ echo "${x%/*}" +# foo/bar +x=foo/bar +if [ "${x%/*}" != foo ] ; then + echo 'Bug 19 present: ${..%..} in double quotes broken' +fi +unset x + +# +# 20. (same as 18) +# + +# +# 21. Everywhere +# 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 +# $ +case -x in +-\?) echo 'Bug 21 present: backslashes do not work in case patterns' +esac + +# +# 22. Quoting backquotes inside backquotes doesn't work: +# $ echo `echo hi \`echo there\` folks` +# asks for more info. sh and at&t ksh both echo +# hi there folks +cat > $tfile << 'EOF' + echo `echo hi \`echo there\` folks` +EOF +out=`$THIS_KSH $tfile 2>&1` +if [ "$out" != 'hi there folks' ] ; then + echo 'Bug 22 present: quoting backquotes inside backquotes broken' +fi +rm -f $tfile + +# +# 23. )) 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 +# $ +cat > $tfile << 'EOF' + ( : ; ( : ; echo hi)) +EOF +out=`$THIS_KSH $tfile 2>&1` +if [ "$out" != 'hi' ] ; then + echo 'Bug 23 present: )) always assumed to be end of (( )) expr' +fi +rm -f $tfile + + +# +# 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]" + +# +# 25. 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. +# +(echo a; echo b) | while read x ; do + [ "$x" = b ] && echo 'Bug 25 present (read reads too much from pipe).' + cat > /dev/null + done + +# +# 26a. Check reading stdin in a while loop. The read should read both +# lines, not just the first. +# +cat > $tfile << 'EOF' + a + b +EOF +cat > $sfile << 'EOF' + a= + while [ "$a" != xxx ] ; do + last=$x + read x + cat /dev/null | sed 's/x/y/' + a=x$a + done + if [ "$last" != b ] ; then + echo 'Bug 26 present (reading in a while loop broken).' + fi +EOF +$THIS_KSH $sfile < $tfile +rm -f $tfile $sfile + +# +# 26b Check reading stdin in a while loop. The read should read both +# lines, not just the first. This differs from 26 in that lines +# are placed against the margin. +# +cat > $tfile << 'EOF' +ab +cd +EOF +cat > $sfile << 'EOF' + a= + while [ "$a" != xxx ] ; do + last=$x + read x + cat /dev/null | sed 's/x/y/' + a=x$a + done + if [ "$last" != cd ] ; then + echo "Bug 26b present (last line should be cd was $last.)" + fi +EOF +$THIS_KSH $sfile < $tfile +rm -f $tfile $sfile + +# +# 27. Everywhere +# The command +# . /does/not/exist +# should cause a script to exit. +cat > $tfile << 'EOF' + . does/not/exist + echo hi +EOF +out=`$THIS_KSH $tfile 2> /dev/null` +if [ "$out" = hi ] ; then + echo "Bug 27 present: .'ing a non-existant file doesn't kill script" +fi +rm -f $tfile + + +# +# 28. Everywhere +# variable assignements not detected well +# +cat > $tfile << 'EOF' + a.x=1 echo hi +EOF +out=`$THIS_KSH $tfile 2> /dev/null` +if [ "$out" = hi ] ; then + echo "Bug 28 present: strange chars allowed in variables" +fi +rm -f $tfile + +# +# 29. Everywhere +# alias expansion different from real ksh +# +cat > $tfile << 'EOF' + alias a='for ' b='i in' + a b hi ; do echo $i ; done +EOF +out=`$THIS_KSH $tfile 2> /dev/null` +if [ "$out" != hi ] ; then + echo "Bug 29 present: keyword in alias with trailing space doesn't work" +fi +rm -f $tfile + + +# +# 30. Everywhere +# strange characters allowed inside ${...} +# +cat > $tfile << 'EOF' + echo ${a{b}} +EOF +out=`$THIS_KSH $tfile 2> /dev/null` +if [ $? = 0 ] ; then + echo 'Bug 30 present: strange chars allowed inside ${..}' +fi +rm -f $tfile + + +# +# 31. Everywhere +# Does read handle partial lines correctly +# +cat > $tfile << 'EOF' +a A Aa +b B Bb +EOF +print -n 'c' >> $tfile +cat > $sfile << 'EOF' + a= + ret= + while [ "$a" != xxx ] ; do + read x y z + ret=$? + a=x$a + done + if [ "$x" != c ] ; then + echo 'Bug 31a present: read throws away partial lines' + fi + if [ "$ret" != 1 ] ; then + echo 'Bug 31b present: read does not return eof for partial lines' + fi +EOF +$THIS_KSH $sfile < $tfile 2> /dev/null +rm -f $sfile $tfile + + +# +# 32. Everywhere +# Does read set variables to null at eof? +# +cat > $tfile << 'EOF' +a A Aa +b B Bb +EOF +cat > $sfile << 'EOF' + a= + while [ "$a" != xxx ] ; do + read x y z + a=x$a + done + if [ -n "$x$y$z" ] ; then + echo "Bug 32 present: read does not set variables to null at eof" + fi +EOF +$THIS_KSH $sfile < $tfile +rm -f $sfile $tfile + + +# +# 33. Everywhere +# Does umask print a leading 0 when umask is 3 digits? +# +cat > $sfile << 'EOF' +umask 222 +umask +EOF +out=`$THIS_KSH $sfile` +if [ X"$out" = X222 ] ; then + echo "Bug 33 present: umask doesn't always start with 0" +fi +rm -f $sfile + + +# +# 34. Everywhere +# Does umask print a umask of 0 sanely? +# +cat > $sfile << 'EOF' +umask 0 +umask +EOF +out=`$THIS_KSH $sfile` +if [ X"$out" = X00 ] ; then + echo "Bug 34 present: umask prints 0 as \`$out'" +fi +rm -f $sfile + +# +# 35. Everywhere +# Tempory files used for here-docs in functions get trashed after +# the function is parsed (before it is executed) +# +cat > $sfile << 'EOF' + f1() { + cat <<- EOF + F1 + EOF + f2() { + cat <<- EOF + F2 + EOF + } + } + f1 + f2 + unset -f f1 + f2 +EOF +out=`$THIS_KSH $sfile 2>&1` +expected='F1 +F2 +F2' +if [ X"$out" != X"$expected" ] ; then + echo "Bug 35 present: here documents in functions don't work" +fi +rm -f $sfile + +# +# 36. Everywhere (test from ) +# Command substitution breaks reading in while loop +# +cat > $sfile << 'EOF' + (echo abcdef; echo; echo 123) | + while read line + do + # the following line breaks it + c=`echo $line | wc -c` + echo $c + done + +EOF +out=`$THIS_KSH $sfile 2>&1` +expect='7 +1 +4' +if [ X"$out" != X"$expect" ] ; then + echo "Bug 36 present: reading broken by command substitution in while loops" +fi +rm -f $sfile + +# +# 37. Machines with broken times() (reported by ) +# time does not report correct real time +# +out=`$THIS_KSH -c 'time sleep 1' 2>&1 | awk ' + /^[ ]*0*\.0*s?[ ][ ]*real/ { print "bad" } + /^[ ]*real[ ][ ]*0*\.0*s?([ ]|$)/ { print "bad" }'` +if [ -n "$out" ] ; then + echo "Bug 37 present: time does not report real-time correctly" +fi + +# +# 38. set -e doesn't ignore exit codes for if/while/until/&&/||/!. +# +out=`$THIS_KSH -e -c ' + if false; then echo hi ; fi + false || true + false && true + while false; do echo hi; done + echo ok' 2>&1` +if [ X"$out" != Xok ] ; then + echo "Bug 38 present: set -e exits when it shouldn't" +fi + +# +# 39. set -e: errors in command substitutions aren't ignored +# +out=`$THIS_KSH -e -c 'if test X\`false; echo hi\` = Xhi; then echo ok ; fi' 2>&1` +if [ X"$out" != Xok ] ; then + echo "Bug 39 present: set -e: errors in command substitutions not ignored" +fi diff --git a/misc/ChangeLog.sjg b/misc/ChangeLog.sjg new file mode 100644 index 0000000..59a014f --- /dev/null +++ b/misc/ChangeLog.sjg @@ -0,0 +1,49 @@ +Fri Dec 3 21:39:47 1993 Piercarlo Grandi (pcg@aber.ac.uk) + + * polished 4.9 for linux; corrected a terrible, linux + specific performance bug that caused all streams to + become unbuffered; made emacs.c more understandable. + With 4.9 pdksh is twice as fast and one third the size + of bash 1.13, and has most of the relevant functionality. + To me it is a drop-in replacement. + +Sat May 8 15:55:24 1993 Simon J. Gerraty (sjg@zen.void.oz.au) + + * Ported to 386bsd - sh directory only, stc/* not needed. + +Sat Aug 1 17:11:24 1992 Simon J. Gerraty (sjg@zen) + + * Incorporated massive contribution from Peter Collinson + Refer to Changes.pc + + * Incorporated Emacs-style completion provided by + Neil.Smithline@eng.sun.com this a bit nicer than the standard ksh + file completion. + +Sun May 3 17:50:03 1992 Simon J. Gerraty (sjg@zen) + + * Updated MACHINES. + * Placed source under CVS. This should help with processing fixes + from the field. + +Sat Apr 25 10:53:20 1992 Simon J. Gerraty (sjg@zen) + + * Getting ready for 4.3 release. + +Fri Nov 22 22:24:29 1991 Simon J. Gerraty (sjg at zen) + + * Cleaned up the build process slightly. Makefiles in ./std tree + now maintain objects within the libraries rather than simply + building the .o's and archiving them. Of course the make(1) used + must know how to maintain libraries :-) + + * Added bug.report as a template for bug reporting. + + * Source in ./sh can be built independently of ./std tree if + desired. See comments in ./sh/Makefile. + + * As originally distributed some of libstdc.a was not used and + libposix.a was not used at all. On Sun's this highlighted a bug + (incompatibility) in the times() call. Now the ./std/libs are + used fully, and the supplied times() call functions as expected. + diff --git a/misc/Changes.jrm b/misc/Changes.jrm new file mode 100644 index 0000000..e4ea79a --- /dev/null +++ b/misc/Changes.jrm @@ -0,0 +1,61 @@ +Changes to the PD ksh since last time: + +- clean up the option configuration stuff. Options in config.h should + now just be #define'd or not, not #define'd to 1 if you want them + and 0 if you don't + +- ksh now uses the shell specified by the variable EXECSHELL to run + shell scripts. If EXECSHELL is unset or null it defaults to + /bin/sh. It does a path lookup on the value, so if you set it to + ``ksh'' the ksh will run all scripts that don't start with #!. It + seems to run most sh scripts fine (now). I'd be very interested to + hear your experiences if you try this out, as for my next trick I'd + like to make ksh just fork itself to run scripts, which would speed + things up, and allow exportable functions and aliases (like he real + ksh). Just to assure you that it can do some hairy sh scripts, both + CC and coco work with ksh. + + EXECSHELL won't work if the system's exec(2) call runs scripts... + +- the ``let'' builtin now evaluates null or unset vars to 0, as per + The Book + +- Various memory allocation/use problems were cleaned up. Hopefully + you'll never see the ``freeing free object'' error again (if you've + ever seen it). + +- the ``test'' builtin is now much more tolerant in parsing its + arguments. This was to make it like the /bin/sh test. + +- Temp files (for here documents or ``fc'') are now mode 0600 + +- Some format strings in the tree printing routines got ``expanded'' + into SCCS keywords, so the results of``type '' were + gave you interesting things like the time I last checked in the + file. This has been fixed. + +- ``unset -f'' now really does unset functions. + +- the ``trailing blank or tab in alias definition'' feature now works. + +- A bug in command completion was fixed. Note command completion only + works on commands that have been hashed, so you want to ``set -h'' + in your .kshrc, and you may wish to force hashing of some common + commands with the ``hash'' builtin. + +- ``echo $$ | cat'' now works as in /bin/sh + +Not new features, but newly discovered bugs: + +- Local functions don't work correctly. This shouldn't be much + problem, since sh doesn't have them. + +- Here documents in functions don't work. This is a problem with the + temp file allocation that requires more work to fix than I've gotten + around to doing. So avoid things like: + +foo() { + cat <<- HereDoc +This is a test +HereDoc +} diff --git a/misc/Changes.mlj b/misc/Changes.mlj new file mode 100644 index 0000000..e53814c --- /dev/null +++ b/misc/Changes.mlj @@ -0,0 +1,44 @@ +I got the pd-ksh from John MacMillan after he indicated that he +had a version of it that had vi editing (I'd seen various versions +with emacs-editing, but none with vi). + +It had a few bugs and areas which were not quite complete. I fixed +(or at least tried) to fix several; there are still some things +which I plan on doing (or at least looking into). + +Bugs fixed (or at least abated): + + vi-mode changes: + - Changed memcpy() to memmove(), which fixed the trashing of + the end of the edit buffer while inserting in the middle + of a line or with use of '#' + - using 'r' replacing the current character with ^@ + - typing ctrl-c resulting in next command being garbled + - lack of support for '-' and '+' (pretty trivial) + - finish adding support for '*' (not entirely sure I'm freeing + malloc'ed memory correctly here, but I haven't had any problems) + - treats '_' as end of a word + + general changes: + - reporting "not found" when a file actually doesn't have + the appropriate execute bit set (now says "cannot execute" + or "not found", as appropriate) + + +Still to do: + + vi changes: + - fix ctrl-r (I've come up with a hack, but it involves + redrawing the screen a lot when it isn't necessary; I + really wouldn't consider this a fix) + - add support for 'v' + + general changes: + - seems to be a memory leak when executing shells in the + current shell; repeatedly executing ". /etc/profile" + increased the size of the program as reported in the + "SZ" field of "ps -l" + - don't give a file its complete pathname in argv[0]; only + its filename (religious issue?) + - history recall should start at the previous command, not + the current one (typing "r r" causes an infinite loop) diff --git a/misc/Changes.pc b/misc/Changes.pc new file mode 100644 index 0000000..29a4688 --- /dev/null +++ b/misc/Changes.pc @@ -0,0 +1,28 @@ +Changes by Peter Collinson - Hillside Systems/BSDI - July 1992 + + +a) Add select command - this cannot be ksh without that. + (It NEEDS typedefs too) +b) Remove all the bcopys from vi.c + add + #define memmove in sh.h for BSD systems +c) Add * command to vi mode - expands to a list of files + using the menu printing routine +d) Add my version of history, that works much like the `proper' ksh + storing data in a file that is shared between different invocations + of the shell. +e) Add the ability to redirect to am expansion... ie + + ls > o* + if o* is unique then it puts it into the file that matches + otherwise it puts it to a file called o*... this is current + behaviour. +f) Add alternations, from Csh.d) This is not part of ksh but is something + that csh users really miss from the Bourne shell derivatives. The idea + is that lists inside curly braces expand to arguments. ie. + exampl{a,b,c,d,e} + will expand to 5 arguments + exampla examplb examplc exampld example + Recursive lists are permitted. +g) Add suspend as a built-in alias. +h) Port to BSD/386 - add _POSIX_TERM and _BSDI as defines. diff --git a/misc/README.sjg b/misc/README.sjg new file mode 100644 index 0000000..67b2433 --- /dev/null +++ b/misc/README.sjg @@ -0,0 +1,118 @@ + Public Domain Korn Shell + Version 4.9 + +PD KSH: + +This is the latest version of the PD ksh (pdksh). It is not intended +to be the ultimate shell but rather a usable ksh work alike. For +those of us who have to work on multiple systems it is nice to have +the same user interface on all. I resisted moving to the ksh on a +System V machine where I worked, for nearly a year due to the lack of +a ksh on my Sun systems. When I first picked up the 3.2 PD KSH a +couple of years ago, it took only a few minutes to convert a C-shell +fan to a ksh fan :-) Pdksh is not 100% compatible with the ksh. +Having said that, I use it daily beside a real ksh88 and find them +virtually indistinguishable. With one exception - arrays! If some +one feels like adding arrays, I for one would appreciate it :-) + +I only run this shell on sun's and BSD systems and only for +interactive use. I use it on sun4c, sun3, sun386 and 386bsd systems. +The shell itself has been compiled on the sun's both with and without +the POSIX/ANSI compatability libraries in ./std. I do not use ./std +for 386bsd and friends. See the file MACHINES for details of systems +that the shell has been built on. + +I released version 4.0 of the shell (with the kind permission of +the previous maintainers and major contributors) to ensure that +it is available from usenet archive sites. Of course it remains +in the Public Domain. Equally obviously neither myself nor any +other contributors make any claims of suitability etc. Ie. NO +WARRANTY!!! If you make any changes and distribute them, please +leave your own finger prints in the source. Its bad enough +being flamed for my own bugs let alone anyone elses :-) + + +HISTORY: + +This shell was written by Eric Gisin. It is based on Charles +Forsyth's public domain V7 shell, which he later contributed to +Minix. John R MacMillan picked up Eric Gisin's version after +Eric moved on to other projects (see ReadMe.jrm). + +Since then there have been many contributors to this shell. +Most have left their fingerprints within the source and various +ReadMe.xxx and Changes.xxx files reflect their input. + +This version is basically that known as Eric Gisin's version 3.3 +alpha which I obtained indirectly from John R MacMillan who is +the most recent maintainer. This version has much improved +emacs-mode command line editing (my main contribution) plus +enough extra emacs-mode features to make it difficult to +distinguish from ksh88. Bug fixes from various contributors are +the only other changes from John MacMillan's version. + +I have upped the version number for this release to distinguish +it from the original 3.3 version. This version is much improved +despite the small number of new features. + +INSTALLATION: + +The file INSTALL contains intructions for building and +installing the shell. + +The original instructions indicated that a POSIX compliant +environment and possibly an ANSI compiler are required. I have +used both gcc and native Sun and the GreenHills ANSI compiler +without problems. + +The POSIX/STDC compatability stuff in ./std seems to cause lots +of problems for some systems. This was at least in part because +I distributed it with half the librraies disabled :-), in any +case the shell itself in ./sh can now be compiled without any of +the ./std stuff which makes things much simpler on systems that +have a real POSIX environment. + +Porting to new environemnts can be a real pain. I don't really +plan to make a huge effort in this area since I expect that this +shell will be mainly required on exotic or obscure systems (the +ones that the vendor does not provide a ksh for). Thus the +small "market" does not warrant a C-news or X11 style +portability effort. Of course if people send patches for +various systems I'm happy to try and integrate them. + +ENVIRONMENT: + +My main interest in this shell is for Sun workstations. Every +other UNIX system I use comes with a real ksh. Being a strictly +C-shell environment, some improved profile files are in order on +Sun's. + +The etc directory contains a set of useful environment files. +These are the same files I use on several systems (many use a +real ksh): +./etc/profile +./etc/sys_config.sh +./etc/ksh.kshrc + +The first one is obvious. The second, sys_config.sh is sourced +by /etc/profile and several other scripts. It is used to +determine the system type so that scripts like profile can be +used on multiple platforms. +The third one is also quite useful, add +. /etc/ksh.kshrc +to user's ~/.kshrc to simplify alias management. + +BUGS: + +Many folk have contributed to this shell. +I have attempted to credit (in sh/ChangeLog) the authors of bug +fixes received since the previous release. +There are surely still plenty of bugs to be found/fixed. + +There is a template bug report in bug-report [borrowed from the +X11R5 mit tree], just fill in the blanks and mail to +pdksh-bug@zen.void.oz.au. + +I hope you find this shell as useful as I do... + +Simon J. Gerraty diff --git a/misc/ReadMe.eg b/misc/ReadMe.eg new file mode 100644 index 0000000..a59c352 --- /dev/null +++ b/misc/ReadMe.eg @@ -0,0 +1,46 @@ + Public Domain KornShell + + Quick installation notes for PD KornShell + +PD KornShell can be installed on 4.2+ BSD systems, System V, and +POSIX-compatable systems. The makefiles all define _BSD, change +this to _SYSV, or _POSIX. The makefiles also contain CC=gcc, +delete this if you don't have GNU C. The ksh makefile also +contains some options, including JOBS (BSD/POSIX job control) +and EDIT (emacs command editing). + +PD KornShell assumes you have standard C (ANSI) and POSIX header +files and functions. Since you probably don't, they are provided +in the "std" directory. + +The Alpha test version will probably come as two tar files. +std.tar contains standard C and POSIX emulation and must be +extracted into a directory called std. ksh.tar contains the ksh +source and should be extracted into a directory called src or +ksh. + +See std/ReadMe and install it. Only then can you make ksh in the +"src" directory. + +To clear up questions about the origin of this shell, this shell +is NOT based on the "Minix shell". It is based on Charles +Forsyth's public domain V7 shell, which he later contributed to +Minix. + +I have permission directly from Charles Forsyth to use his shell. + + Eric Gisin, egisin@math.UWaterloo.CA (or Waterloo.EDU) + + Things to do +- add sxt-based job control (see Brown's contribution on the Usenix 87 tape). +- add arrays and variable attributes. +- add MAILPATH and CDPATH. +- add vi editing mode (apparently someone has a PD version). +- add new features described in Korn's book. + + Machines ported to +VAX, 68000, 80386 + + OS's ported to +BSD 4.2, BSD 4.3 (with and without YP and NFS +Sys V.3 diff --git a/misc/ReadMe.emacs b/misc/ReadMe.emacs new file mode 100644 index 0000000..a304438 --- /dev/null +++ b/misc/ReadMe.emacs @@ -0,0 +1,88 @@ +HORIZONTAL SCROLLING +==================== + +I have migrated my 3.2 ksh edit.c mods into the 3.3 ksh +This file describes the mods in general and really only applies +(at this stage) to emacs-mode. I have not touched vi-mode apart +from making it use pprompt() so that '!' is correctly expanded +as in emacs-mode. + +I would prefer to see both vi.c and emacs.c use a common set of +primatives in edit.c - but that looks like a lot of work. + +Basically my mods affect the functions that move the cursor +about and redraw the edit line. + +The input buffer "buf" is pointed to by "xbuf" and its end is +pointed to by "xend". The current position in "xbuf" and end of +the edit line are pointed to by "xcp" and "xep" respectively. +I have added "xbp" which points to the start of a display window +within "xbuf". + +[A] starting position + +buf +|<-------- $COLUMNS --------->| +| |<---- x_displen ------->| +| PS1| + +==========+==============--------+.......+ + |\ \ \ \ + xbuf xbp xcp xep xend + +[B] scrolled + +buf +| |<----- COLUMNS -------->| +| |<----- x_displen ------>| +| ++-----------+==========+==============--------+.......+ + \ \ \ \ \ + xbuf xbp xcp xep xend + +In the above -------- represents the current edit line while +===== represents that portion which is visible on the screen. +Note that initially xbp == xbuf and PS1 is displayed. +PS1 uses some of the screen width and thus "x_displen" is less +than $COLUMNS. + +Any time that "xcp" moves outside the region bounded by "xbp" +and "xbp" + "x_displen", the function x_adjust() is called to +relocate "xbp" appropriately and redraw the line. + +Excessive I/O is avoided where possible. x_goto() for instance +calculates whether the destination is outside the visible +region, and if so simply adjusts "xcp" and calls x_adjust() +directly. Normally though x_adjust() is called from x_putc(). + +The above mechanism has be updated to use a function x_lastcp() +that returns a pointer that accurately reflects the last +visible char in the edit buffer. That is a more accurate +version of xbp + x_displen which does not account for TABS. + +Other changes +============= + +I have also added some emacs mode functions. +M-[0-9] + Set a numeric arg (positive only). + Used by all word related commands. +M-_ +M-. + Retrieve word from previous command (default is last + word). Use M-[1-9] to select word. +M-u +M-l +M-c + UPPER,lower,Capitalize word. + + +Commands like delete-word now push the deleted text so that it +may be yanked back into place. + +BUGS? +===== + +There are bound to be some. Please report same to me: + +Simon J. Gerraty + diff --git a/misc/ReadMe.jrm b/misc/ReadMe.jrm new file mode 100644 index 0000000..2441704 --- /dev/null +++ b/misc/ReadMe.jrm @@ -0,0 +1,118 @@ +BUILDING THE PD KSH +=================== + +As usual, there are differences between BSD and System V +versions. Ideally, all you have to do is edit the Makefile in +this directory to set the CONFIG macro to the appropriate value. +(Actually, you may wish to change the CONFIG macro in all +Makefiles; if you always invoke make(1) from here, CONFIG will +be passed down, but if you invoke make(1) from a subdirectory +you'll want the appropriate definition in that Makefile.) + +Of course it's not quite that simple. You may, however, take +solace in the knowledge that it used to be worse. + +The Compatibility Libraries +--------------------------- + +Eric Gisin wrote this shell using ANSI C and POSIX as +portability guidlines. Realizing that nobody had a POSIX +system and almost no one had an ANSI C environment, he provided +minimal compatibility libraries. + +There are two libraries, one for POSIX (libposix.a) and one for +ANSI C (libstdc.a). + +Libposix.a is pretty simple. Nothing in it has ever broken on +me, so I'd just leave it. It provides a version of dup2() for +System V systems. + +Libstdc.a is a bit hairy. I recommend looking at the routines +provided and, and editing the std/stdc Makefile and only +including objects that have routines your system libc.a is +lacking. Various of the provided routines are just plain +flaky, but only when they're not really needed. The other +hairy thing he does is craft an ANSI stdio.h from the system +supplied one and one of his own. Again, it's better than it +used to be, but it's still a hack, and you may have to modify +it by hand. + +You will also need a POSIX compatible set of directory reading +routines. System V.3 systems have this in libc.a. The +std/posix directory provides a something for BSD systems. I +use a slightly modified version of Doug Gwyn's PD version. + +(The ``slightly modified'' is to work around a bug in Gwyn's version. +The POSIX routines are documented as returning failure if the file for +opendir(3) is not a directory. Gwyn attempts to open(2) the file, and +then stats it to see if the file is a directory. However, if the file +is a special file, and the open(2) doesn't return, you're screwed. My +change was to open the file with the O_NDELAY flag, but Gwyn didn't +feel this was portable (true, but I only do it where it works) and +that stat-ing before the open would be too slow (true). The upshot is +if you use his routines unmodified, don't ever do an "ls -l /dev/*/*".) + +The Shell Source +---------------- + +The source for the shell itself is in the sh directory. There you +will want to edit config.h to determine the configuration options. Vi +mode is in kind of rough shape, but does work. DIRSTACK routines +aren't implemented yet, so again, why bother. SWTCH is a bit arcane, +but it you use shl(1) and you define EMACS or VI you want to define +this. JOBS is really only useful on BSD systems. It might work on +systems that have POSIX job control, but I wouldn't bet on it. +SHARPBANG is only useful on systems where the exec() family don't +honour the #!/prog/path convention. + +This is where the shell gets built so you may wish to change +the OTHERLIBS macro in the Makefile to point to your POSIX +directory routines, or to use -lc_s, or whatever. + +Miscellaneous +------------- + +The Makefiles that actually compile things use the macro +CCOPTS, so you can change it in individual Makefiles or specify +it on the command line, eg. "make CCOPTS=-O OTHERLIBS=-lc_s". +LDOPTS is used in the Makefile where the ksh is actually built. + +The very first time on a new system, do a "make clobber" + +Good luck. + +Documentation +------------- + +The ksh.1 is a man page for the PD ksh, although it lags +somewhat behind the code. You get what you pay for. + +The ksh88.1 is a man page for AT&T's ksh88 (the latest version) +provided for comparison. + +History +------- + +Much of the shell was written by Eric Gisin at the University +of Waterloo, using some pieces of other stuff, notably Charles +Forsythe's V7 shell, and some enhancements from the BRL shell. +He placed it (in a alpha test state) into the public domain +while I was at UW. I snarfed a copy, and got it running on my +UNIXpc, and later some machines at work. I sent Gisin some bug +reports, but he seems to have lost interest in the project. +This may be because he now does some work for MKS, who produce a +commercial version of the ksh for MS-DOS machines, so there may +be a conflict of interest. + +So I gave up on getting future versions, and adopted it. I've +made some enhancements, and quite a few bug fixes, and various +people at work have contributed as well. It remains in the +public domain, although I imagine the people involved would +appreciate leaving their names attached (I'm exempt; I haven't +actually included my name anywhere but here). + +The README in the sh directory is Gisin's, and tells a bit of +the story from his point of view. Note that his compilation +instructions don't really apply anymore. + +John R. MacMillan diff --git a/mkinstalldirs b/mkinstalldirs new file mode 100644 index 0000000..0e29377 --- /dev/null +++ b/mkinstalldirs @@ -0,0 +1,35 @@ +#!/bin/sh +# Make directory hierarchy. +# Written by Noah Friedman +# Public domain. + +defaultIFS=' +' +IFS="${IFS-${defaultIFS}}" + +errstatus=0 + +for file in ${1+"$@"} ; do + oIFS="${IFS}" + # Some sh's can't handle IFS=/ for some reason. + IFS='%' + set - `echo ${file} | sed -e 's@/@%@g' -e 's@^%@/@'` + IFS="${oIFS}" + + pathcomp='' + + for d in ${1+"$@"} ; do + pathcomp="${pathcomp}${d}" + + if test ! -d "${pathcomp}"; then + echo "mkdir $pathcomp" 1>&2 + mkdir "${pathcomp}" || errstatus=$? + fi + + pathcomp="${pathcomp}/" + done +done + +exit $errstatus + +# eof diff --git a/mkman b/mkman new file mode 100644 index 0000000..0466660 --- /dev/null +++ b/mkman @@ -0,0 +1,44 @@ +#!/bin/sh + +verbose=no + +if [ X"$1" = X-v ] ; then + verbose=yes + shift +fi +if [ $# != 2 ] ; then + echo "Usage: $0 [-v] which-shell ksh.Man-file" 1>&2 + exit 1; +fi +shell=$1 +man=$2 + +case $shell in + sh) which=0;; + ksh) which=1;; + *) + echo "$0: bad shell option (must be sh or ksh)" 1>&2 + exit 1 + ;; +esac +if [ ! -r "$man" ] ; then + echo "$0: can't read $man file" 1>&2 + exit 1; +fi + + +# +# Now generate the appropriate man page... +# +[ $verbose = yes ] && echo "$0: Generating $which man page (0=sh,1=ksh)..." 1>&2 + +awk 'BEGIN { ksh = '$which'; pr = 1 } + /^\.sh\(/ { pr = ksh - 1; next } + /^\.sh\)/ { pr = 1; next } + /^\.ksh\(/ { pr = ksh; next } + /^\.ksh\)/ { pr = 1; next } + { if (pr) print $0 } ' < $man + +[ $verbose = yes ] && echo "$0: All done" 1>&2 + +exit 0 diff --git a/new-version.sh b/new-version.sh new file mode 100644 index 0000000..c015b60 --- /dev/null +++ b/new-version.sh @@ -0,0 +1,75 @@ +#!/bin/sh + +# +# Update the date in the version file (version.c). If the existing +# date is todays date, a .number is apprended (or incremented) to +# make them distinct. +# Also update the version number and date in tests/version.t and ksh.Man. +# + +# pattern that matches the date in the version string in version.c +# \1 is preamble (@(#)PD KSH ), +# \2 is the version (v1.2.3 ), +# \3 is the date (99/03/21.3), +# \4 is postamble (...) +# (use ? pattern delimiters). +DATEPAT='\(.*@(#).* \)\(v[.0-9]* \)\([0-9]*/[0-9]*/[.0-9]*\)\(.*\)' + +vfile=version.c +vfiles="version.c tests/version.t ksh.Man" + +version=`sed -n "s?$DATEPAT?\2?p" < $vfile` +odatev=`sed -n "s?$DATEPAT?\3?p" < $vfile` +odate=`echo "$odatev" | sed 's?\..*??'` +ov=`echo "$odatev" | sed 's?[^.]*\.*??'` + +date=`date '+%y/%m/%d' 2> /dev/null` +case "$date" in +[0-9]*/[0-9]*/[0-9]*) ;; +*) + # old system - try to compensate... + date=`date | awk 'BEGIN { + months["Jan"] = 1; months["Feb"] = 2; months["Mar"] = 3; + months["Apr"] = 4; months["May"] = 5; months["Jun"] = 6; + months["Jul"] = 7; months["Aug"] = 8; months["Sep"] = 9; + months["Oct"] = 10; months["Nov"] = 11; months["Dec"] = 12; + } { + if (months[$2]) + mon = sprintf("%02d", months[$2]); + else + mon = $2; + printf "%02d/%s/%02d\n", $6 % 100, mon, $3; + }'` +esac + +if test x"$odate" = x"$date"; then + v=".$ov" + if test -z "$ov" ; then + v=1 + else + v=`expr $ov + 1` + fi + date="$date.$v" +fi + +for i in $vfiles; do + bfile=$i.bak + tfile=$i.new + # try to save permissions/ownership/group + cp -p $i $tfile 2> /dev/null + if sed "s?$DATEPAT?\1$version$date\4?" < $i > $tfile; then + if cmp -s $i $tfile; then + echo "$i not changed, not updating" + rm -f $tfile + else + rm -f $bfile + ln $i $bfile || exit 1 + mv $tfile $i || exit 1 + fi + else + echo "$0: error creating new $i" 1>&2 + exit 1 + fi +done + +exit 0 diff --git a/os2/Makefile b/os2/Makefile new file mode 100644 index 0000000..507fac2 --- /dev/null +++ b/os2/Makefile @@ -0,0 +1,323 @@ +# +# OS2_Makefile +# + +srcdir = . +VPATH = . + +CC = gcc +CPP = cpp + +INSTALL = /bin/install -c +INSTALL_PROGRAM = $(INSTALL) +INSTALL_DATA = $(INSTALL) -m 644 + +DEFS = -DHAVE_CONFIG_H +LIBS = -los2 + +CPPFLAGS = +CFLAGS = -O -DOS2 +LDSTATIC = +LDFLAGS = -O -s $(LDSTATIC) + +SHELL_PROG = ksh + +prefix = c:/usr +exec_prefix = c:/usr +transform=@program_transform_name@ + +bindir = $(exec_prefix)/bin +mandir = $(prefix)/man/man$(manext) +manext = 1 + +# Suffix for executables: nothing for unix, .exe for os/2. +exe_suffix=.exe + +SHELL = sh + +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 sigact.c syn.c table.c trap.c \ + tree.c tty.c var.c version.c vi.c +OBJS = os2.o alloc.o c_ksh.o c_sh.o c_test.o c_ulimit.o edit.o emacs.o \ + eval.o exec.o expr.o history.o io.o jobs.o lex.o mail.o \ + main.o misc.o missing.o path.o shf.o sigact.o syn.o table.o trap.o \ + tree.o tty.o var.o version.o vi.o +HDRS = c_test.h edit.h expand.h ksh_dir.h ksh_limval.h ksh_stat.h ksh_time.h \ + ksh_times.h ksh_wait.h lex.h proto.h sh.h shf.h sigact.h \ + table.h tree.h tty.h +DISTFILES = $(SRCS) $(HDRS) ksh.Man Makefile.in configure.in \ + config.h.in conf-end.h acconfig.h aclocal.m4 emacs-gen.sh \ + mkinstalldirs install-sh new-version.sh siglist.in siglist.sh mkman \ + check-fd.c check-pgrp.c check-sigs.c \ + README NEWS CONTRIBUTORS LEGAL PROJECTS INSTALL NOTES BUG-REPORTS \ + IAFA-PACKAGE ChangeLog ChangeLog.0 configure stamp-h.in +# ETCFILES also disted, but handled differently +ETCFILES = etc/ksh.kshrc etc/profile etc/sys_config.sh +# MISCFILES also disted, but handled differently +MISCFILES = misc/ChangeLog.sjg misc/Changes.jrm misc/Changes.mlj \ + misc/Changes.pc misc/README.sjg misc/ReadMe.eg misc/ReadMe.emacs \ + misc/ReadMe.jrm misc/Bugs +# TESTFILES also disted, but handled differently +TESTFILES = tests/README tests/th tests/th-sh tests/alias.t tests/arith.t \ + tests/bksl-nl.t tests/brkcont.t tests/cdhist.t tests/eglob.t \ + tests/glob.t tests/heredoc.t tests/history.t tests/ifs.t \ + tests/integer.t tests/lineno.t tests/read.t tests/regress.t \ + tests/syntax.t tests/unclass1.t tests/unclass2.t \ + tests/version.t +# OS2FILES also disted, but handled differently +OS2FILES = os2/Makefile os2/config.h os2/config.status os2/configure.cmd \ + os2/emacs.out os2/kshrc.ksh os2/make.sed os2/os2.c os2/os2siglist.out \ + os2/README.os2 os2/NEWS.os2 os2/os2bugs os2/th.cmd os2/config.cache + +all: $(SHELL_PROG)$(exe_suffix) $(SHELL_PROG).1 + +# This shouldn't be first - some makes don't know about PRECIOUS and assume it +# is the default target. +.PRECIOUS: configure config.h.in Makefile config.status + +.c.o: + $(CC) -c $(CPPFLAGS) $(DEFS) -I. -I$(srcdir) $(CFLAGS) $< + +install: installdirs all + $(INSTALL_PROGRAM) $(SHELL_PROG)$(exe_suffix) $(bindir)/$(SHELL_PROG)$(exe_suffix) + -$(INSTALL_DATA) $(SHELL_PROG).1 $(mandir)/$(SHELL_PROG).$(manext) + -@prog=$(bindir)/$(SHELL_PROG)$(exe_suffix);\ + test -f /etc/shells \ + && (grep "^$$prog\$$" /etc/shells > /dev/null \ + || echo \ +"NOTE: /etc/shells does not contain $$prog \ + you should add it if you want to set your shell to $(SHELL_PROG)") + +installdirs: + $(srcdir)/mkinstalldirs $(bindir) $(mandir) + +uninstall: + rm -f $(bindir)/$(SHELL_PROG)$(exe_suffix) + rm -f $(mandir)/$(SHELL_PROG).$(manext) + +check test: + th.cmd $(srcdir)/tests/th -s $(srcdir)/tests -p ./$(SHELL_PROG)$(exe_suffix) -C pdksh,sh,ksh,posix,posix-upu $(TESTARGS) + +$(SHELL_PROG)$(exe_suffix): $(OBJS) + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) + +# two steps to prevent the creation of a bogus tmpksh.1 +$(SHELL_PROG).1: $(srcdir)/ksh.Man + $(srcdir)/mkman $(SHELL_PROG) $(srcdir)/ksh.Man > tmpksh.1 + mv tmpksh.1 $(SHELL_PROG).1 + +info: + @echo "No info (yet)" + +dvi: + +$(srcdir)/configure: configure.in aclocal.m4 + cd $(srcdir) && autoconf + +$(srcdir)/config.h.in: stamp-h.in +$(srcdir)/stamp-h.in: configure.in aclocal.m4 acconfig.h + cd $(srcdir) && autoheader + date > $(srcdir)/stamp-h.in + +config.h: +cmd /c copy $(srcdir)\os2\config.h config.h > nul +touch config.h +Makefile: +cmd /c copy $(srcdir)\os2\Makefile Makefile > nul +touch Makefile +# two steps to prevent the creation of a bogus siglist.out +siglist.out: +cmd /c copy $(srcdir)\os2\os2siglist.out siglist.out > nul +touch siglist.out +# two steps to prevent the creation of a bogus emacs.out +emacs.out: +cmd /c copy $(srcdir)\os2\emacs.out emacs.out > nul +touch emacs.out +debugtools: check-fd$(exe_suffix) check-sigs$(exe_suffix) \ + check-pgrp$(exe_suffix) + +check-fd.o check-pgrp.o check-sigs.o: config.h +check-fd$(exe_suffix): check-fd.o + $(CC) $(LDFLAGS) -o $@ check-fd.o $(LIBS) + +check-pgrp$(exe_suffix): check-pgrp.o + $(CC) $(LDFLAGS) -o $@ check-pgrp.o $(LIBS) + +check-sigs$(exe_suffix): check-sigs.o + $(CC) $(LDFLAGS) -o $@ check-sigs.o $(LIBS) + +TAGS: $(SRCS) $(HDRS) + cd $(srcdir) && etags $(SRCS) $(HDRS) + +tags: $(SRCS) $(HDRS) + cd $(srcdir) && ctags -wt $(SRCS) $(HDRS) + +clean: + rm -f ksh$(exe_suffix) sh$(exe_suffix) ksh.1 sh.1 $(OBJS) siglist.out \ + emacs.out core a.out mon.out gmon.out \ + version.c.bak Makefile.bak Makefile.tmp check-fd$(exe_suffix) \ + check-pgrp$(exe_suffix) check-sigs$(exe_suffix) + +mostlyclean: clean + +distclean: clean + rm -f Makefile config.h stamp-h config.status config.log config.cache \ + tags TAGS *~ + +realclean: distclean + +dist: $(DISTFILES) $(ETCFILES) $(MISCFILES) $(TESTFILES) $(OS2FILES) + cd $(srcdir) && \ + { \ + ./new-version.sh; \ + FNAME=pdksh-`sed -e '/"@(.)/!d' \ + -e 's/[^0-9]*\([0-9.]*\).*/\1/' -e q version.c`; \ + if test `echo $$FNAME|tr . ' '|wc -w|sed 's/[ ]*//g'` -gt 3; \ + then \ + FNAME=`echo $$FNAME | sed 's/pdksh-/pdksh-unstable-/'`; \ + fi; \ + echo Creating version $$FNAME; \ + rm -rf $$FNAME; \ + mkdir $$FNAME $$FNAME/etc $$FNAME/misc $$FNAME/tests $$FNAME/os2; \ + cp -p $(DISTFILES) $$FNAME; \ + cp -p $(ETCFILES) $$FNAME/etc; \ + cp -p $(MISCFILES) $$FNAME/misc; \ + cp -p $(TESTFILES) $$FNAME/tests; \ + cp -p $(OS2FILES) $$FNAME/os2; \ + ./emacs-gen.sh emacs.c > os2/emacs.out; \ + test -x ./Dist-fixup && ./Dist-fixup $$FNAME; \ + sed -f os2/make.sed < $$FNAME/Makefile.in > $$FNAME/os2/Makefile; \ + chmod -R a+rX,u+w,og-w $$FNAME; \ + tar chzf $$FNAME.tar.gz $$FNAME; \ + find $$FNAME -print | xargs pathchk -p; \ + } + +depend: $(SRCS) + sed -n '1,/[ ]PUT ANYTHING BELOW THIS LINE/p' < Makefile > Makefile.tmp + srcs=; for i in $(SRCS) ; do srcs="$$srcs $(srcdir)/$$i"; done; \ + $(CC) -M $(DEFS) -I. -I$(srcdir) $(CFLAGS) $$srcs | \ + sed -e 's?[ ]/[^ ]*??g' -e 's?[ ]./? ?g' \ + -e 's?[ ]$(srcdir)//*? ?g' -e 's?^$(srcdir)//*??' \ + -e '/^[ ]*\\[ ]*$$/d' -e '/^[^:]*:[ ]*$$/d' \ + -e 's/^\([ ]*\)$$/ sh.h/' \ + >> Makefile.tmp + mv Makefile.tmp Makefile + @echo 'Make depend done (stopping make)'; false + +# DON'T PUT ANYTHING BELOW THIS LINE (and don't delete it - its for make depend) +alloc.o: alloc.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h +c_ksh.o: c_ksh.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h ksh_stat.h \ + sh.h +c_sh.o: c_sh.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h ksh_stat.h ksh_time.h \ + ksh_times.h \ + sh.h +c_test.o: c_test.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h ksh_stat.h c_test.h +c_ulimit.o: c_ulimit.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h ksh_time.h \ + sh.h +edit.o: edit.c config.h conf-end.h sh.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h tty.h \ + edit.h \ + ksh_stat.h +emacs.o: emacs.c config.h conf-end.h sh.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h ksh_stat.h ksh_dir.h \ + edit.h emacs.out +eval.o: eval.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h \ + ksh_dir.h \ + ksh_stat.h +exec.o: exec.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h c_test.h \ + ksh_stat.h +expr.o: expr.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h \ + sh.h +history.o: history.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h ksh_stat.h +io.o: io.c \ + sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h ksh_stat.h +jobs.o: jobs.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h ksh_stat.h ksh_wait.h \ + ksh_times.h ksh_time.h \ + tty.h \ + sh.h +lex.o: lex.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h \ + sh.h +mail.o: mail.c config.h conf-end.h sh.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h ksh_stat.h ksh_time.h \ + sh.h +main.o: main.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h ksh_stat.h ksh_time.h \ + sh.h +misc.o: misc.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h \ + sh.h +missing.o: missing.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h ksh_stat.h ksh_dir.h \ + ksh_time.h \ + ksh_times.h \ + sh.h +path.o: path.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h ksh_stat.h +shf.o: shf.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h ksh_stat.h ksh_limval.h \ + sh.h +sigact.o: sigact.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h +syn.o: syn.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h c_test.h +table.o: table.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h +trap.o: trap.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h siglist.out +tree.o: tree.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h +tty.o: tty.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h ksh_stat.h tty.h \ + sh.h +var.o: var.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h ksh_time.h \ + ksh_limval.h \ + ksh_stat.h \ + sh.h +version.o: version.c sh.h config.h conf-end.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h +vi.o: vi.c config.h conf-end.h sh.h \ + shf.h table.h tree.h expand.h lex.h \ + proto.h \ + ksh_stat.h edit.h diff --git a/os2/NEWS.os2 b/os2/NEWS.os2 new file mode 100644 index 0000000..ae0a6bc --- /dev/null +++ b/os2/NEWS.os2 @@ -0,0 +1,106 @@ +Version 5.2.6 + + 1. The bug where hereis documents would leave temporary files behind has + been fixed. + + 2. Changed extension search order to place .exe files ahead of files with + no extension. This permits the gcc option -Zexe to work properly, + however it causes some limitations. Should this be a problem then I will + have to detect and ignore zero length files without an extension as a + special case for gcc. I would prefer not to do this. + + 3. Increased the number of file descriptors available to 40. This corrects + a problem that showed up on some warp connect systems. + + 4. Allowed any extension to be used for a script so long as the user + explicitly types it in. + +Version 5.2.4 + + 1. You can now open multiple files in a script, i.e. exec works. Some + better checking could still be done. + + 2. A bug in reading input files where data was getting shifted around + has been fixed. (forced binary mode to emx a number of places for input.) + + 3. Directories with same name as executables will no longer cause an error. + + 4. OS2 cmd processing of extproc header line only passes the file name + to the spawned process instead of the full pathname. This is a bug + in os2 IMHO since if you explicitely want a certain path for the + command you cannot guarantee it. A change was made to search the + path within ksh to permit this processing to work. Note that the + copy ksh finds might not be the one you wanted but at least you can + copy your cmd files around without having to modify them. A side + effect of this change is that typing: "ksh whatis" will now search + your path as well which does change the standard behavior of ksh. + + 5. #! processing will now search for the shell using the explicit path + and if not found then it will use the path variable. + Most of you won't notice any difference since the shell will still + be found but if you needed a particular one then this can be done. + Note that if you only want a particular pathname use "\"'s in the path. + + 6. Ksh will now honor the advertised EXECSHELL variable if it is set + instead of OS2_SHELL as the shell to be used if there is no + #! or extproc line in the file. The difference is EXECSHELL will not + have any options supplied while OS2_SHELL will automatically get + /c and the pathname will have '\' as the directory separator. + OS2_SHELL will still be used if EXECSHELL is not set. + + 7. A new option to print, -f, has been added for os2 users. It will + force forward slashes. It is useful when trying to massage an + environmental variable containing backslashes using something like + sed which always interpretes backslashes as escapes. There is + and example of this in the new kshrc.ksh that I have included. + + 8. Working with os2 variables can be a pain try to escape all of the ';'s + so I have supplied some new functions in the kshrc.ksh. Please + checkout add_path, pre_path, and del_path. These functions will + append a path, prepend a path, or delete a path from the variable + you specify, PATH by default. These are modification of the + samples shipped with the unix pdksh startup files. + + 9. The echo output and other outputs from ksh now use forward slashes + and in general forward slashes will be seen more often than before. + Backslashes will still be accepted on input and command line + completion but it was too painful to try and preserve the os2 look + for output and permit Unix scripts to work. If you prefer the + old method change the variable DIRSEP in sh.h and rebuild. + +10. A bug requiring all command extensions to be in lower case was + fixed. This showed up most often in the setting of OS2_SHELL. + +11. os2/configure will now set up to build either ksh or sh. + + +Version 5.2.2 + +o OS2 executable can be built directly from original sources! No patches + required. Just unload, cd to source directory, run os2\configure, and + then make (v3.73 minimum), nmake, or dmake. +o Built on emx09a. (513 was built on 08.) +o Now uses full signal processing from emx. Previous version used fake + signals. Better and more accurate signal status. +o TMPDIR variable can now point to a another drive. Which can be a FAT + drive. +o Improved case folding in vi mode for file name matches. +o Vi mode can now use cursor keys if desired. (Like emacs mode) +o Both vi and emacs mode now get a set of default stty settings. ^C + and ^U should now work during command line editing. +o #!/bin/sh and similar lines at the top of scripts are now stripped + of pathname prefixes permitting use of standard OS2 search paths. + This should permit better shell script portability. +o case statement variable usage is now case sensitive. Also applies + to several other variable constructions. +o Now accepts .sh as an executable extension. +o All commands that start a new window are automatically backgrounded. +o ksh can usually be made to grok gnu configure scripts but the results + are still very script dependant. See the readme.os2 for details. + + +Version 5.1.3 + +This was the original version 5 release based on an earlier port of +4.9 by Kai Rommel. + diff --git a/os2/README.os2 b/os2/README.os2 new file mode 100644 index 0000000..9f7cdad --- /dev/null +++ b/os2/README.os2 @@ -0,0 +1,498 @@ + OS/2 port of pdksh version 5 + June, 1996 + +Introduction + +This document is intended to define the specific features and +differences in the os/2 port of pdksh. For general features and +descriptions of pdksh itself please refer to the standard pdksh README +or the man page. In general the port has tried to maintain as many of +the standard ksh features as possible. For installation details and +an introduction to ksh please read the README.1st file shipped in the +run time zip package for os2. + +A default build of pdksh, called ksh.exe, is included in the os2 +run time package. This version was built using the emx environment and +therefore requires that an emx run time package 0.9b or later be +installed on the system. This is not normally a problem since you +probably already installed it for 'ls' and other Unix commands from +the file gnufutil.zip. (If you haven't install gnufutil.zip you may +want to consider it.) + +Building KSH.EXE + +If you would rather build your own, you should obtain the sources from +ftp.cs.mun.ca in the directory pub/pdksh. You will need a copy of tar +and gunzip to unload the archive and install on an hpfs partition. Change +to the source directory and run the script os2\configure.cmd. (If you +prefer you can copy configure.cmd to the source directory.) This will +prepare the build environment so that your version of make can be used +to build the executable. Note that configure.cmd is still under +construction and you may need to make changes to the Makefile and to +config.h to match your specific needs. Copies of all of these files +will be placed into the source directory. In addition you may want to +make changes to config.h to define your particular preferences. +Configure.cmd for os2 support these optional options and arguments: + /h | /? | -h Print a usage message and exit. + /v | -v Print verbose output during configure + /d | -d build a debug version with symbols (for gcc) + sh build sh rather than ksh +Any configuration other that the default requires that sed be in your +search path. You should always get a copy of the latest pre-built version +of ksh as well since the file os2bugs may contain some last minute fixes +that were too late to include in the formal release, and you may find some +other updates. In addition the run time version supplies a couple of +sample icons for use with ksh. + +At this point you can use your favorite make command to build the +executable. Pdksh is known to work with nmake and dmake, gnu make requires +at least version 3.7.3 and is the only one that will automatically make the +man page. You can manually run mkman after starting your new copy of ksh, +'ksh mkman ksh|sh ksh.man'. (A prebuilt sh and expanded cat version of +ksh.1 is included in the rt package.) + +There is a built in check routine that is part of the makefile. Type +'make check' to run it. This routine needs a copy of perl on your +machine in order to support the test harness used to test the build. I +have built the infrastructure into the port to support this checking but +have not been able to get it all to run correctly yet. The problem is +because of a bug in the os2 port of ksh. To check the build without using +perl, run the command: 'ksh Bugs ksh'. This will use the older checking +facility. You should run this if you make any changes to the source to +insure that you haven't broken something crucial. Run make check on an +unmodified version first so that you will know what to expect. If you +want to get the perl version running please contact me for information. + +KSH 5 VERSUS KSH 4.9 + +The KSH version 5 effort is being spearheaded by Michael Rendell. Michael +took over the effort from Simon J. Gerraty who maintained the version 4 +code. While the version 4 code was a good implementation of ksh +version 5 strives to continue the conformance to the actual posix +definitions and to AT&T ksh. + +For my version 5 port to os/2, I originally started with the 4.9 os/2 +changes and applied them to the new version. Subsequently many changes +have been made so that there is little resemblance to that version. +One of my goals for version 5 is to make ksh not only and interactive +shell, but one that can run some limited Unix(tm) shell scripts as well. + +Generally the two shells behave the same. Version 5 has no logout script +(This can be set up using a trap in your profile.ksh file if desired.) and +the option 'hashall' has been replaced with 'trackall'. (To see all of the +options use the command 'set -o'.) In addition the prompt has been changed +to conform with the at&t ksh shell instead of the csh like implemetation of +version 4. The '!' sign is used for the history number and $variable +substitutions can be used in the prompt. The commands generally behave more +consistently. For example bind now goes to standard out so it can be +redirected or piped. Arrays are now implemented as are almost all AT&T ksh +features plus a few more. The os/2 port provides file name completion that +is not case sensitive. The startup file kshrc.ksh is still supported, but +the way it works is slightly different. + +OS2 IMPLEMENTATION VS. UNIX + +The original OS/2 port was done by Kai Uwe Rommel. I have re-implemented +his ideas in this os/2 version. The os/2 version of ksh has been modified +to accept the standard os/2 conventions. Drive designations a:, etc., are +accepted and path separators in variables have been changed to ';'. In +addition either '/' or '\' can be used as a directory separator. The bind +command in emacs mode has been enhanced to accept function key and alt key +bindings. (To see what the alt key binding should be, use ^Q followed by +the key you are interested in. Replace the ^ alpha you see with ^0, typed +as two characters, in the bind command.) The cursor keys have been +implemented for command history for both emacs mode and vi insert mode. +Standard default stty settings are implemented for both modes as well. +A os2 only print option, -f, can be used to force forward slashes in its +argument. This can be used to switch a variable containing '\' to +output '/' in a pipe to a unix command that doesn't like '\' as a path +separator, such as sed. + +/ vs. \ processing + +The remapping of certain keys can lead to some confusion for Unix and OS/2 +users. The '\' key has a different meaning in Unix where it is used +to escape a special meaning for the character following it or in the +case of the echo (typeset) command it provides special meanings to +certain characters. At the end of a line the '\' is used to escape the +line feed permitting a command to extend to multiple lines. In OS/2 +this key is generally the directory name separator. To provide for +both functions in the OS/2 pdksh the '\' is defined to be a directory +separator in any pathname specification and will keep its escape +meaning when it is followed by any non-alphanumeric character. The +echo command retains its special interpretation of '\' and will, for +example, interpret \t as a tab when printing. This can be +disconcerting when you echo the variable that you just set to c:\tmp. +If you want to use echo on a variable with pathnames in it you should +either use uppercase names or a '/' as a separator. Another choice is +to alias echo to 'print -r' or perhaps 'echo -E'. This will disable +the special interpretaions. You could even use the new 'print -f' to +force any '\' to switch to '/', but this is less portable. If you have +loaded the printenv command it can be used to look at variables. + +Unix uses '/' as a directory separator and the OS/2 implementation +permits and in some cases prefers this use as well. Generally you +can freely mix '/' and '\' characters in a pathname. However, 'cd \' +will not complete since '\' will escape the new line command and you +will get the secondary prompt. Just enter a / and the command will +complete. For many standard os/2 commands the '/' is used to indicate an +option and may want a '\' as a path separator. These will still work and +be correctly interpreted with pdksh as long as a '/' is not attached +directly to the command name. Just be sure and enter the syntax needed +by the command you are trying to execute. + +While backslash processing is usually correct and automatic there are times +when it doesn't do what you might expect. For example ls \tmp\*.exe might +surprise you. In this case the '\' will be interpreted as an escape for +the '*' character. You may need quotes or several backslashes to get what +you want. Beginning with 5.2.4 the output of ksh favors '/' for any +generated pathnames. This is intended to make script processing for +unix scripts easier. Unfortunately, this may make interactive use for +os2 users that prefer the '\' key a little less desirable. Should you +prefer the earlier convention then you can rebuild the executable from +the sources. Only one change in sh.h, DIRSEP, controls this behavior. + +; vs. : processing + +Another conflict is the use of ':' and ';'. Unix uses ':' to separate +entries in variable assignment and ';' to indicate multiple commands +on the same line. OS/2 uses the ';' to separate entries in a variable. +This could lead to problems when making an assignment to a variable in +pdksh. You will need to escape the ';' in OS/2 to prevent the shell +from interpreting it as the end of the command. Either surround the +assignment command with quotes or use '\;'. Note that since a ';' is +not a valid filename or pathname character the '\' will be correctly +interpreted as an escape character. + +Since having to escape the ';' character can be a pain when changing +environmental variables containing a list of paths there are some functions +defined in the sample kshrc.ksh file to ease this task. There are three +functions; add_path, pre_path, and del_path that can be used to append a +path, prepend a path or delete a path from any environmental variable (PATH +by default). If you needed to add a path to /emx/bin you might do "add_path +e:\emx\bin" for example, or perhaps "add_path e:\emx\book BOOKSHELF" to add +some books to the bookshelf. Note that you will need a copy of sed in your +search path to use the del_path function. + +In OS/2 the ':' is used to separate the drive letter from the rest of +the pathname. This usage had been preserved in pdksh. You can imbed +the drive letter as needed in pathnames. In addition pdksh preserves +the notion of separate contexts for each drive. To change drives you +would use the cd command. "cd A:/" would change to the root on drive +A while "cd C:." would change to whatever was current context on drive +C. Some aliases are defined in the sample kshrc.ksh to permit the +usual A: to automatically do a change directory to the A drive. + +Wildcard Processing + +OS/2 and pdksh have similar notions about wildcard characters '*' and +'?' except that pdksh handles the expansion of these wildcard within +the shell and then passes the answer as a list to the application. If +the application needs to see the wildcard character then you must +escape it from the shell. Note that pdksh knows about other wildcard +techniques as well. Please see the man page. + +Background Processing + +Do to some limitations in the os2 fork process and other differences +between os2 and unix it is not possible to support back-grounding from +pdksh of commands that begin a new window. For this reason I have +automatically backgrounded all such tasks when they are started. This +will permit the os2 ksh to serve as a command line launch mechanism for +dos, full screen, and pm applications. (Note that currently ksh can only +launch an application of the same type (windowed, or fullscreen) that +ksh itself is unless you use the 'start' alias. + +There is a 'start' alias defined in the sample kshrc.ksh file that can +be used to start normal command line commands in a new window. For example +you could say "start ksh" to start a copy of ksh itself in a new window. +Since it is a new window it will automatically return control to the existing +copy of ksh. Note that the start alias uses the os2 start command so +you could supply it with any standard start option such as /FS to force +a full screen copy. Please check your os2 command reference manual for +further information on start. + +PDKSH, OS/2 and the ENVIRONMENT. + +The environment in OS/2 and Unix are quite different. For one thing +you don't actually login to your machine in OS/2 and your initial +environment is established by your CONFIG.SYS file. The Shell will use +the variables that were set in CONFIG.SYS and you should really +consider assigning TMPDIR and HOME for use by pdksh. It will also use +ENV as a variable that names a startup file that will run each time +the shell is started, even if a script is started. This start up file +is located in your home directory. For compatability with 4.9 this +shell will also automatically use a startup shell kshrc.ksh if it +finds one in your home directory, is started interactively, and $ENV +is not set. + +The variable OS2_SHELL should point to cmd.exe or a fully compatible +version and will be used as the shell of choice for any scripts that you +write that do not contain the #! or extproc information in the top line +of the script. If you prefer you can set the variable EXECSHELL to a +shell to be used instead of OS2_SHELL. The use of OS2_SHELL assumes that +the shell requires the /c option and that the shell needs all pathnames +separated with '\'. Setting EXECSHELL will disable both of these +assumptions. + +A special feature is the support of the -l, login option. If this option is +entered when starting ksh then the shell will execute a loginfile called +profile.ksh if located in $INIT/etc, c:/usr/etc, or your home. If you are +using this shell as your primary shell you may wish to change the settings +in your os2 command shell notebook to call ksh.exe -l. I would not +recommend changing the default shell in config.sys. + +Should you destroy your PATH variable try 'unset PATH'. A default +path may get you going again. In addition pdksh for OS/2 always uses +commands from current context first in the search path even if it is +not explicitly set. By default c: drive is used when no variables +are set. Specifically c:/usr/bin and c:/usr/etc can be used as defaults +various places in ksh. If you build your own version then this can be +changed. + +Generally all of the environmental variables described in the man page will +work in OS2 so long as the tools in use understand them in the same way +as Unix would. + +Using KSH + +The shell itself can be called any name you wish. Good names include +pdksh.exe, ksh.exe, sh.exe. You can build two completely different +shells using the options file. A full blown Korn shell can be built +or a complete subset that behaves very much like a Bourne shell. The +smaller version is excellent for script support. In the run time +release I have provided the full shell under the name ksh.exe and the +smaller version under the name sh.exe. Be careful with names like +rksh.exe or you could end up with a restricted shell that can't do +everything. + +In Unix an executable can be tagged with an attribute to +make it known to the system as an executable. In OS/2 this is done +with an extension. This shell knows all of the standard OS/2 +extensions plus .ksh and .sh. (Yes it can run dos commands and OS/2 command +files as well.) The .ksh or .sh extension tells the shell that this is an +executable shell script. The current version will also treat a file +without an extension as an executable in the style of Unix. Scripts need not +necessarily be a ksh shell scripts however. The standard Unix #! line at +the top of the file determines the actual shell that will be used to run +the script. A feature in this release is that any Unix absolute +pathnames will be tried and, if they fail a second try will be made by +stripping the path from the #! line since Unix style paths are unlikely +to match os2 usage. Your standard PATH search path will be used. +Should the same filename with a different extension exist in the same +directory pdksh will use the extension typed in by the user or if +no extension is entered then the search order is, .ksh, .exe, no extension, +.sh, .cmd, .com, .bat. This search order permits ksh scripts to be used to +modify binary executable behavior while allowing the -Zexe option for emx +gcc. . Note that if you explicitly type the extension yourself then any +extension can be used so long as the #! processing line is at the top of +the file to let pdksh know what to do. + +The sample kshrc.ksh file that comes with the distribution can be used as +an example that shows you how to create aliases that will simulate the +standard OS/2 commands. This means you can still use copy, dir, and del if +you want to. Keyboard bindings supplied will still provide the command +stack and suddenly you also have command line completion and alias +capability. To get the most from the shell you will probably want the set +of Unix commands developed by the Gnu team and ported to os2. You will +most certainly need them or a similar set if you want to run any Unix +scripts. A few functions are also provided in the sample kshrc.ksh file to +demonstrate the power of functions and to ease common tasks. + +Unix file systems are case sensitive and ksh generally expects this also. +This means that internal commands as well as aliases are case sensitive. +You can use this to your advantage. For example you might want to run a dos +shell only to find out that 'command' is captured as an internal command by +ksh. Try 'COMMAND' or even 'Command' and you will get what you wanted. +The file name completion and wild card expansion has been modified for os2 +to permit it to ignore case. + +Working with Editing Modes + +As delivered ksh for os2 supports three different editing modes to use +with the command line. By default the editing mode is the same as that +used in cmd.exe in that F1, F2, and F3 can be used to edit the previous +command. Left and right cursor keys can also be used to edit the command. +Support for this comes directly from the emx layer. The history mechanism +is supported in this mode but you will not be able to scroll trhough +history from the command line. Pdksh commands exist to display and edit +history and the EDITOR environmental variable can be set to specify the +editor you want. Two other mutually exclusive editing modes exist as well. + +The sample kshrc.ksh file turns on emacs editing mode. In this mode +pdksh emulates the commands and keyboard binding present in emacs. The +keyboard binding is fully customizable by the user using the bind command. +For os2 the default build includes support of the cursor keys to edit +both current and previous commands. The sample kshrc.ksh file includes +some further mapping as examples of keyboard binding. The bind -m +command can be used to define special macro commands. Note that in emacs +the ESC key following by a letter key is usually synonymous with holding +down the ALT key and pressing a letter key. In the current os2 implementation +these keys are not tied together so they could be programmed independantly +although this could be confusing for the user. This may change in the +future. + +Issuing the command 'set -o vi' turns on vi mode. This mode emulates the +keyboard binding from the vi editor. In addition using the tab key for +command line completion is separately programmable using the set command. +For os2 the cursor keys are also set up to work from within insert mode to +allow editing of both the current and previous commands without ever +leaving insert mode. The Esc Shft-A sequence can be used to jump to the end +of the line allowing you to append new information to the line. CTRL-X, +CTRL-E and CTRL-F permit command line completion within insert mode. Thus +you can use vi mode without ever having to learn traditional vi commands. + +SHELL SCRIPT PROGRAMMING + +One of my goals in porting this shell was to be able to do shell level +script programming and to run Unix shell scripts with minimal modification. +The first goal is easy and fully functional in this release. You can write +shell scripts for this or other shells. The name of the shell you want to +run the script is entered in the first line of the script itself after a +'#!' sequence. If you only enter the name of the command then pdksh will +use your search path to find the shell. This is the recommended approach, +however absolute paths of the form /bin/ etc. will be stripped +automatically if needed to permit running Unix scripts unmodified. To write +portable scripts use the 'uname' command from Gnu to set a variable that +can be checked for specialized approaches. As a special case absoulte +paths using '\' will not be stripped and an error will be generated if +the command is not found at the exact path specified. + +It is even possible to use ksh as a scripting language when your main +shell is a standard OS/2 shell. To do this you would write your ksh +script as usual except that the first line in the script should read +'extproc ksh'. The script should be named with a '.cmd' extension so +that the OS/2 shell can find it. When the cmd.exe finds this line in +the file it will call ksh to process the script for you. A script +that is written this way can also be called directly from ksh. As a +matter of fact you could use this technique entirely for script +creation and name all your scripts with the .cmd extension. Pdksh +will honor 'extproc' exactly like the standard Unix '#!' processing. + +Unlike Unix #! processing the OS2 cmd processing of an extproc header line +only passes the file name to the spawned process instead of the full +pathname. This is a bug in os2 IMHO since if you explicitely want a +certain path for the command you cannot guarantee it. The workaround was to +put the path in the extproc line and then shift the extra filename off the +argument list. For example my whatis.cmd file used to start like this. + + extproc ksh c:/usr/bin/whatis.cmd + shift + +You can still do this, but ksh will also search the path to find a copy +of the command, so this is no longer required. Of course, the copy that ksh +finds might not be the one you wanted but at least you can copy your cmd +files around without having to modify them. A side effect of this change +is that typing: "ksh whatis" will now search your path as well which does +change the standard behavior of ksh which some might construe as a feature! + +The second goal of running Unix scripts with little or no modification is +much more difficult to achieve. Unix makes many assumptions about how the +system is set up which makes fully portable scripts difficult to accomplish +without the knowledge of the script internals. Many script assume the +presense of /dev/null and /tmp. (The emx layer provides an automatic map +for shell references to /dev/null and /dev/tty as of the 0.9a version and +pdksh also maps /dev/null to nul for the cases where emx doesn't see it +unless a /dev/null is present.) Some scripts assume /bin and certain +commands within /bin (usually cp and sh). Until I can figure out how to +make this more transparent you can simply make these directories on the +drive that you intend to run the script on. (Of course, you could also +modify the script.) Some scripts reset the PATH variable near the beginning +of the script. While you could copy a whole set of commands it is probably +easier to modify the script or use tvfs (more about tvfs later.) Another +standard "trick" in Bourne shell script programming is to modify IFS to +include a colon and then use the set command to parse a variable by setting +$1, $2, etc. In OS/2 this would need to be a ';'. For now you will have to +hand modify the script. + +The latest release of ksh for os2 now supports multiple open files +using standard pdksh syntax. Note that error checking may not be +as complete as standard pdksh for some of this usage. + +Of course Unix scripts expect the presence of Unix commands. You will +need to install a set of Unix utilities, Unix text processing +commands, and probably sed and a version of awk. I have created a +c:/usr directory on my system for Unix stuff. I have /usr/bin, +/usr/man, /usr/etc, /usr/home, and /usr/local. You could establish +even more, or perhaps less, Unix conformance. You will also need a ps +command. I use procs.exe which I renamed to ps.exe. Kill is a ksh +builtin. + +RUNNING UNIX GNU CONFIGURE SCRIPTS. + +A lot of people would like to use pdksh to permit them to run the +gnu automatic configure scripts. I am pleased to report that this +is possible using pdksh. However, I can't guarantee that the results +will match the true configuration for os2 since this is dependant on +the way the individual configure scripts are written. + +To set up to run configure scripts you will need to have a copy of pdksh +called sh.exe somewhere in your path and, of course, you should be +running within a pdksh shell. One of the very early things done +by most configure scripts is to figure out the compiler. This will fail +since it depends on setting the IFS (see the above discussion). To +workaround this problem simply set CC to the compiler you want to use +prior to running the script. For example to use gcc: 'export CC=gcc'. +Most configure scripts couldn't figure out the names of os2 compilers +anyway. Now you should be able to simply type 'configure' and watch it +work. At some point the configure script will build a config.status +script to perform the final step. If this is not run using 'sh -c +config.status' or some such it will fail since .status is not an os2 +legal executable suffix. You can run it manually however by typing +'ksh config.status'. If you have problems you should inspect the +config.status script and fix it as required. Using ksh -x config.status +will echo the lines as they are executed which should aid in debug. + +Many configure scripts actually build and execute programs to test +for certain features. In OS2 using emx, the final link step must have +the .exe extension tied to the executable name or the linker will not +link correctly. You will need to modify the configure script to +insure the correct executable name. Once this is built it can be +renamed to a name without an extension if ksh is being used to run it. +A line similar to the following may work for you if you are using 2.0: + +ac_link='${CC-cc} -o conftest.exe $CFLAGS $CPPFLAGS $LDFLAGS \ +conftest.$ac_ext $LIBS && mv conftest.exe conftest' + +This trick takes advantage of ksh's ability to run a command without an +extension. Even with these changes you may still find that configure does +not correctly identify some os2 features. I would recommend that the +config.cache file be edited as required or the resulting config.h file. + +Another trick is to use the -Zexe option to gcc. This builds a zero length +file without an extension and the real executable with the extension .exe. +Makefiles and some configure scripts may be fooled by this behavior. + +TVFS + +An IBM employee written program called tvfs, toronto virtual file system, +can be downloaded from most os2 ftp sites and from IBM ftp sites. This +program permits you to simulate a Unix like file system that can span +physical drives and even network drives. Using tvfs you cd once into the +drive letter designated as the tvfs drive and from then on you can +reference all of your drives and directories by only using Unix style +pathnames if you wish. Even a limited form of symbolic links can be set +up on this drive. This can be a great aid in running Unix scripts and +makefiles as well as configure scripts. + +WORK IN PROGRESS + +There is still much to do and this project will probably never be complete. +The configure.cmd file needs work as does the Makefile. Please let me know +if you get this to compile using a C compiler other than gcc. The standard +defaults work in the Makefile but many other things are not implemented. +And of course there are bugs to fix and enhancements to be made. Check the +file os2bugs in the run time release for the latest information on bugs. + +Please let me know if you like this port, have found a porting bug, +have fixed a bug, or have coded a spiffy enhancement. Michael Rendell +should be consulted for general pdksh items and is now actually +maintaining and enhancing all of the code. Please check the standard +README for more information and also the file os2bugs for current known +problems and limitations. I can be reached at daled@cadence.com. + +Note that this is a home brew project and is in no way related to my +employment. + + Dale DePriest + diff --git a/os2/config.cache b/os2/config.cache new file mode 100644 index 0000000..20d521f --- /dev/null +++ b/os2/config.cache @@ -0,0 +1,91 @@ +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +ac_cv_c_const=${ac_cv_c_const='yes'} +ac_cv_c_cross=${ac_cv_c_cross='no'} +ac_cv_decl_sys_siglist=${ac_cv_decl_sys_siglist='no'} +ac_cv_func_confstr=${ac_cv_func_confstr='no'} +ac_cv_func_flock=${ac_cv_func_flock='yes'} +ac_cv_func_getwd=${ac_cv_func_getwd='no'} +ac_cv_func_killpg=${ac_cv_func_killpg='no'} +ac_cv_func_mmap=${ac_cv_func_mmap='no'} +ac_cv_func_nice=${ac_cv_func_nice='no'} +ac_cv_func_setrlimit=${ac_cv_func_setrlimit='no'} +ac_cv_func_sigsetjmp=${ac_cv_func_sigsetjmp='yes'} +ac_cv_func_strcasecmp=${ac_cv_func_strcasecmp='no'} +ac_cv_func_strerror=${ac_cv_func_strerror='yes'} +ac_cv_func_strstr=${ac_cv_func_strstr='yes'} +ac_cv_func_sysconf=${ac_cv_func_sysconf='yes'} +ac_cv_func_tcsetpgrp=${ac_cv_func_tcsetpgrp='yes'} +ac_cv_func_ulimit=${ac_cv_func_ulimit='yes'} +ac_cv_func_wait3=${ac_cv_func_wait3='no'} +ac_cv_func_waitpid=${ac_cv_func_waitpid='yes'} +ac_cv_header_dirent_dirent_h=${ac_cv_header_dirent_dirent_h='yes'} +ac_cv_header_fcntl_h=${ac_cv_header_fcntl_h='yes'} +ac_cv_header_limits_h=${ac_cv_header_limits_h='yes'} +ac_cv_header_memory_h=${ac_cv_header_memory_h='yes'} +ac_cv_header_paths_h=${ac_cv_header_paths_h='no'} +ac_cv_header_stat_broken=${ac_cv_header_stat_broken='no'} +ac_cv_header_stddef_h=${ac_cv_header_stddef_h='yes'} +ac_cv_header_stdlib_h=${ac_cv_header_stdlib_h='yes'} +ac_cv_header_string_h=${ac_cv_header_string_h='yes'} +ac_cv_header_sys_param_h=${ac_cv_header_sys_param_h='yes'} +ac_cv_header_sys_resource_h=${ac_cv_header_sys_resource_h='yes'} +ac_cv_header_sys_time_h=${ac_cv_header_sys_time_h='yes'} +ac_cv_header_time=${ac_cv_header_time='yes'} +ac_cv_header_ulimit_h=${ac_cv_header_ulimit_h='no'} +ac_cv_header_values_h=${ac_cv_header_values_h='no'} +ac_cv_lib_dir=${ac_cv_lib_dir='no'} +ac_cv_path_install=${ac_cv_path_install=''./install-sh -c''} +ac_cv_prog_CC=${ac_cv_prog_CC='gcc'} +ac_cv_prog_CPP=${ac_cv_prog_CPP=''gcc -E''} +ac_cv_prog_gcc=${ac_cv_prog_gcc='yes'} +ac_cv_prog_gcc_g=${ac_cv_prog_gcc_g='yes'} +ac_cv_prog_gcc_traditional=${ac_cv_prog_gcc_traditional='no'} +ac_cv_sizeof_int=${ac_cv_sizeof_int='4'} +ac_cv_sizeof_long=${ac_cv_sizeof_long='4'} +ac_cv_struct_st_rdev=${ac_cv_struct_st_rdev='yes'} +ac_cv_sys_interpreter=${ac_cv_sys_interpreter='no'} +ac_cv_type_clock_t=${ac_cv_type_clock_t='yes'} +ac_cv_type_getgroups=${ac_cv_type_getgroups='gid_t'} +ac_cv_type_mode_t=${ac_cv_type_mode_t='yes'} +ac_cv_type_off_t=${ac_cv_type_off_t='yes'} +ac_cv_type_pid_t=${ac_cv_type_pid_t='yes'} +ac_cv_type_rlim_t=${ac_cv_type_rlim_t='no'} +ac_cv_type_signal=${ac_cv_type_signal='void'} +ac_cv_type_sigset_t=${ac_cv_type_sigset_t='yes'} +ac_cv_type_uid_t=${ac_cv_type_uid_t='yes'} +ksh_cv_c_func_attr=${ksh_cv_c_func_attr='yes'} +ksh_cv_c_prototypes=${ksh_cv_c_prototypes='yes'} +ksh_cv_c_void=${ksh_cv_c_void='yes'} +ksh_cv_c_volatile=${ksh_cv_c_volatile='yes'} +ksh_cv_decl_sys_errlist=${ksh_cv_decl_sys_errlist='no'} +ksh_cv_dev_fd=${ksh_cv_dev_fd='no'} +ksh_cv_dup2_clexec_broken=${ksh_cv_dup2_clexec_broken='no'} +ksh_cv_func_lstat=${ksh_cv_func_lstat='no'} +ksh_cv_func_memmove=${ksh_cv_func_memmove='yes'} +ksh_cv_func_memset=${ksh_cv_func_memset='yes'} +ksh_cv_func_times_broken=${ksh_cv_func_times_broken='no'} +ksh_cv_header_sys_wait_h=${ksh_cv_header_sys_wait_h='yes'} +ksh_cv_header_unistd=${ksh_cv_header_unistd='yes'} +ksh_cv_opendir_nondir=${ksh_cv_opendir_nondir='no'} +ksh_cv_os_type=${ksh_cv_os_type='OS2_EMX'} +ksh_cv_pgrp_check=${ksh_cv_pgrp_check='none'} +ksh_cv_rlim_check=${ksh_cv_rlim_check='long'} +ksh_cv_signal_check=${ksh_cv_signal_check='v7'} +ksh_cv_signal_retval=${ksh_cv_signal_retval=''} +ksh_cv_term_check=${ksh_cv_term_check='termio'} +ksh_cv_time_delcared=${ksh_cv_time_delcared='yes'} +ksh_cv_var_sys_errlist=${ksh_cv_var_sys_errlist='yes'} +ksh_cv_var_sys_siglist=${ksh_cv_var_sys_siglist='no'} diff --git a/os2/config.h b/os2/config.h new file mode 100644 index 0000000..7d9ae6a --- /dev/null +++ b/os2/config.h @@ -0,0 +1,345 @@ +/* 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 doesn't define. */ +/* #undef gid_t */ + +/* Define if you have a working `mmap' system call. */ +/* #undef HAVE_MMAP */ + +/* Define if your struct stat has st_rdev. */ +#define HAVE_ST_RDEV 1 + +/* Define if you have that is POSIX.1 compatible. */ +#define HAVE_SYS_WAIT_H 1 + +/* Define if you have . */ +#define HAVE_UNISTD_H 1 + +/* Define if on MINIX. */ +/* #undef _MINIX */ + +/* Define to `int' if doesn't define. */ +/* #undef mode_t */ + +/* Define to `long' if doesn't define. */ +/* #undef off_t */ + +/* Define to `int' if 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 do not work properly. */ +/* #undef STAT_MACROS_BROKEN */ + +/* Define if `sys_siglist' is declared by . */ +/* #undef SYS_SIGLIST_DECLARED */ + +/* Define if you can safely include both and . */ +#define TIME_WITH_SYS_TIME 1 + +/* Define to `int' if 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 #! */ +#define SHARPBANG 1 + +/* 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.) */ +/* #undef POSIX_SIGNALS */ + +/* 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) */ +#define V7_SIGNALS 1 + +/* Define to use the fake posix signal routines (sigact.[ch]) */ +/* #define USE_FAKE_SIGACT 1 */ + +/* 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 */ +/* #undef POSIX_PGRP */ + +/* 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 */ +#define NO_PGRP 1 + +/* 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 doesn't define */ +/* #undef clock_t */ + +/* Define to the type of struct rlimit fields if the rlim_t type is missing */ +#define rlim_t long + +/* Define if time() is declared in */ +#define TIME_DECLARED 1 + +/* Define to `unsigned' if 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 */ +/* #undef SYS_ERRLIST_DECLARED */ + +/* Define if sys_siglist[] is in the C library */ +/* #undef HAVE_SYS_SIGLIST */ + +/* Define if you have a sane 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 */ +/* #undef HAVE_LSTAT */ + +/* Define if you have a sane header file */ +#define HAVE_TERMIO_H 1 + +/* 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 */ +#define OS2 1 + +/* Define if you have a POSIX.1 compatiable */ +#define POSIX_SYS_WAIT 1 + +/* Define if your OS maps references to /dev/fd/n to file descriptor n */ +/* #undef HAVE_DEV_FD */ + +/* Default PATH (see comments in configure.in for more details) */ +#define DEFAULT_PATH "c:/usr/bin;c:/os2;/os2" + +/* 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. */ +#define SIZEOF_LONG 4 + +/* Define if you have the _setjmp function. */ +/* #undef HAVE__SETJMP */ + +/* Define if you have the confstr function. */ +/* #undef HAVE_CONFSTR */ + +/* 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. */ +/* #undef HAVE_GETWD */ + +/* Define if you have the killpg function. */ +/* #undef HAVE_KILLPG */ + +/* Define if you have the nice function. */ +/* #undef HAVE_NICE */ + +/* Define if you have the setrlimit function. */ +/* #undef HAVE_SETRLIMIT */ + +/* Define if you have the sigsetjmp function. */ +#define HAVE_SIGSETJMP 1 + +/* Define if you have the strcasecmp function. */ +/* #undef HAVE_STRCASECMP */ + +/* 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. */ +#define HAVE_ULIMIT 1 + +/* Define if you have the wait3 function. */ +/* #undef HAVE_WAIT3 */ + +/* Define if you have the waitpid function. */ +#define HAVE_WAITPID 1 + +/* Define if you have the header file. */ +#define HAVE_DIRENT_H 1 + +/* Define if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* Define if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_NDIR_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_PATHS_H */ + +/* Define if you have the header file. */ +#define HAVE_STDDEF_H 1 + +/* Define if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_SYS_DIR_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_SYS_NDIR_H */ + +/* Define if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_RESOURCE_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_WAIT_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_ULIMIT_H */ + +/* Define if you have the 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/os2/config.status b/os2/config.status new file mode 100644 index 0000000..5138d39 --- /dev/null +++ b/os2/config.status @@ -0,0 +1,2 @@ +extproc ksh +echo Please run os2/configure. diff --git a/os2/configure.cmd b/os2/configure.cmd new file mode 100644 index 0000000..2b22aee --- /dev/null +++ b/os2/configure.cmd @@ -0,0 +1,111 @@ +@echo off +if "%1" == "/h" goto help +if "%1" == "/?" goto help +if "%1" == "-h" goto help +set verbose=no +set debug=no +set ushell=ksh +:parse +if "%1" == "/v" goto verbose +if "%1" == "-v" goto verbose +if "%1" == "/d" goto gdebug +if "%1" == "-d" goto gdebug +if "%1" == "sh" goto usersh +if exist os2 goto start +echo You are in the wrong directory. Change to source directory. +echo Copy this file and run again or type os2\configure. +goto end +:verbose +set verbose=yes +shift +goto parse +:gdebug +set debug=yes +shift +goto parse +:usersh +if %verbose% == yes echo Configuring for Bourne shell. +set ushell=sh +:start +if exist conftest.c erase conftest.c +if exist confdefs.h erase confdefs.h +if %verbose% == yes echo Searching for sed +:::::for %%i in (%path%) do if exist %%i\sed.exe goto s_success +sed --version && goto s_success +echo No sed in search path. Copying Makefile for gcc. You will need +echo to edit it if you are not using standard defaults. +copy os2\Makefile Makefile +goto copystuff +:help +echo Run os2\configure to set up for os/2 compilation. +echo You must have current context in the source directory. +echo usage: configure [[/v^|-v][/d^|-d]^|/h^|-h^|/?] [sh] +echo where /v means verbose output +echo /d means compile with symbols (debug) +goto end +:s_success +if %verbose% == yes echo checking for compiler +for %%i in (%path%) do if exist %%i\gcc.exe goto g_success +gcc --version && goto g_success +rem for the future we'll use sed processing +for %%i in (%path%) do if exist %%i\bcc.exe goto b_success +for %%i in (%path%) do if exist %%i\icc.exe goto i_success +echo Compiler not found. Check your path +goto end +:b_success +echo Borland C compiler found. Configuration not complete for +echo this compiler. You may need to edit the Makefile +set CC=bcc +set CPP=cpp +goto createstuff +:i_success +echo IBM C compiler found. Configuration not complete for +echo this compiler. You may need to edit the Makefile. +set CC=icc -q -Sm -Gm -Gt -Spl -D__STDC__ +set CPP=cpp +goto createstuff +:checkshell +if %ushell% == sh goto fixshell +goto copystuff +:g_success +echo GNU C compiler found. This is the standard configuration. +copy os2\Makefile Makefile +if %debug% == no goto checkshell +set CC=gcc -g +set CPP=cpp +:createstuff +echo Creating files for you. +echo s/@CC@/%CC%/> os2\make.tmp +echo s/@CPP@/%CPP%/>> os2\make.tmp +echo s/@LDFLAGS@/-O/>> os2\make.tmp +if %ushell% == ksh goto skipsh +:fixshell +echo s!/bin/sh!ksh!>> os2\make.tmp +echo s/@SHELL_PROG@/sh/>> os2\make.tmp +:skipsh +copy os2\make.tmp+os2\make.sed os2\make.tmp +sed -f os2\make.tmp Makefile.in > Makefile +del os2\make.tmp +:copystuff +if %verbose% == yes echo Copying config.h and config.status files. +copy os2\config.h config.h +touch config.h +copy os2\config.status config.status +if %verbose% == yes echo Checking for os2.c and th.cmd. +if not exist os2.c copy os2\os2.c os2.c +if not exist th.cmd copy os2\th.cmd th.cmd +if %ushell% == ksh goto end +if %verbose% == yes echo Fixing config.h for building sh. +echo #ifdef KSH>> config.h +echo #undef KSH>> config.h +echo #undef VI>> config.h +echo #undef EMACS>> config.h +echo #undef EDIT>> config.h +echo #undef COMPLEX_HISTORY>> config.h +echo #undef EASY_HISTORY>> config.h +echo #undef HISTORY>> config.h +echo #undef BRACE_EXPAND>>config.h +echo #endif>> config.h +:end + + diff --git a/os2/emacs.out b/os2/emacs.out new file mode 100644 index 0000000..fe110d8 --- /dev/null +++ b/os2/emacs.out @@ -0,0 +1,132 @@ +/* + * NOTE: THIS FILE WAS GENERATED AUTOMATICALLY FROM emacs.c + * + * DO NOT BOTHER EDITING THIS FILE + */ +#define XFUNC_abort 0 +static int x_abort ARGS((int c)); +#define XFUNC_beg_hist 1 +static int x_beg_hist ARGS((int c)); +#define XFUNC_comp_comm 2 +static int x_comp_comm ARGS((int c)); +#define XFUNC_comp_file 3 +static int x_comp_file ARGS((int c)); +#define XFUNC_complete 4 +static int x_complete ARGS((int c)); +#define XFUNC_del_back 5 +static int x_del_back ARGS((int c)); +#define XFUNC_del_bword 6 +static int x_del_bword ARGS((int c)); +#define XFUNC_del_char 7 +static int x_del_char ARGS((int c)); +#define XFUNC_del_fword 8 +static int x_del_fword ARGS((int c)); +#define XFUNC_del_line 9 +static int x_del_line ARGS((int c)); +#define XFUNC_draw_line 10 +static int x_draw_line ARGS((int c)); +#define XFUNC_end_hist 11 +static int x_end_hist ARGS((int c)); +#define XFUNC_end_of_text 12 +static int x_end_of_text ARGS((int c)); +#define XFUNC_enumerate 13 +static int x_enumerate ARGS((int c)); +#define XFUNC_eot_del 14 +static int x_eot_del ARGS((int c)); +#define XFUNC_error 15 +static int x_error ARGS((int c)); +#define XFUNC_goto_hist 16 +static int x_goto_hist ARGS((int c)); +#define XFUNC_ins_string 17 +static int x_ins_string ARGS((int c)); +#define XFUNC_insert 18 +static int x_insert ARGS((int c)); +#define XFUNC_kill 19 +static int x_kill ARGS((int c)); +#define XFUNC_kill_region 20 +static int x_kill_region ARGS((int c)); +#define XFUNC_list_comm 21 +static int x_list_comm ARGS((int c)); +#define XFUNC_list_file 22 +static int x_list_file ARGS((int c)); +#define XFUNC_literal 23 +static int x_literal ARGS((int c)); +#define XFUNC_meta1 24 +static int x_meta1 ARGS((int c)); +#define XFUNC_meta2 25 +static int x_meta2 ARGS((int c)); +#define XFUNC_meta_yank 26 +static int x_meta_yank ARGS((int c)); +#define XFUNC_mv_back 27 +static int x_mv_back ARGS((int c)); +#define XFUNC_mv_begin 28 +static int x_mv_begin ARGS((int c)); +#define XFUNC_mv_bword 29 +static int x_mv_bword ARGS((int c)); +#define XFUNC_mv_end 30 +static int x_mv_end ARGS((int c)); +#define XFUNC_mv_forw 31 +static int x_mv_forw ARGS((int c)); +#define XFUNC_mv_fword 32 +static int x_mv_fword ARGS((int c)); +#define XFUNC_newline 33 +static int x_newline ARGS((int c)); +#define XFUNC_next_com 34 +static int x_next_com ARGS((int c)); +#define XFUNC_nl_next_com 35 +static int x_nl_next_com ARGS((int c)); +#define XFUNC_noop 36 +static int x_noop ARGS((int c)); +#define XFUNC_prev_com 37 +static int x_prev_com ARGS((int c)); +#define XFUNC_prev_histword 38 +static int x_prev_histword ARGS((int c)); +#define XFUNC_search_char_forw 39 +static int x_search_char_forw ARGS((int c)); +#define XFUNC_search_char_back 40 +static int x_search_char_back ARGS((int c)); +#define XFUNC_search_hist 41 +static int x_search_hist ARGS((int c)); +#define XFUNC_set_mark 42 +static int x_set_mark ARGS((int c)); +#define XFUNC_stuff 43 +static int x_stuff ARGS((int c)); +#define XFUNC_stuffreset 44 +static int x_stuffreset ARGS((int c)); +#define XFUNC_transpose 45 +static int x_transpose ARGS((int c)); +#define XFUNC_version 46 +static int x_version ARGS((int c)); +#define XFUNC_xchg_point_mark 47 +static int x_xchg_point_mark ARGS((int c)); +#define XFUNC_yank 48 +static int x_yank ARGS((int c)); +#define XFUNC_comp_list 49 +static int x_comp_list ARGS((int c)); +#define XFUNC_expand 50 +static int x_expand ARGS((int c)); +#define XFUNC_fold_capitialize 51 +static int x_fold_capitialize ARGS((int c)); +#define XFUNC_fold_lower 52 +static int x_fold_lower ARGS((int c)); +#define XFUNC_fold_upper 53 +static int x_fold_upper ARGS((int c)); +#define XFUNC_set_arg 54 +static int x_set_arg ARGS((int c)); +#define XFUNC_comment 55 +static int x_comment ARGS((int c)); +#ifdef SILLY +#define XFUNC_game_of_life 56 +static int x_game_of_life ARGS((int c)); +#else +#endif +#ifdef DEBUG +#define XFUNC_debug_info 57 +static int x_debug_info ARGS((int c)); +#else +#endif +#ifdef OS2 +#define XFUNC_meta3 58 +static int x_meta3 ARGS((int c)); +#else +#endif diff --git a/os2/kshrc.ksh b/os2/kshrc.ksh new file mode 100644 index 0000000..e876f70 --- /dev/null +++ b/os2/kshrc.ksh @@ -0,0 +1,118 @@ +# kshrc.ksh startup file for OS/2 version of ksh + +set -o trackall +set -o ignoreeof + +alias a:='cd a:.' +alias b:='cd b:.' +alias c:='cd c:.' +alias d:='cd d:.' +alias e:='cd e:.' +alias f:='cd f:.' +alias g:='cd g:.' +alias h:='cd h:.' +alias i:='cd i:.' +alias j:='cd j:.' +alias k:='cd k:.' +alias l:='cd l:.' +alias m:='cd m:.' + +alias h='fc -l' +alias j='jobs' +#alias which='type' +alias back='cd -' +alias cls='print -n "\033[H\033[2J"' + +alias dir='cmd /c dir' +alias del='cmd /c del' +alias erase='cmd/c erase' +alias copy='cmd /c copy' +alias start='cmd /c start /f' +alias path='print -r $PATH' + +alias ll='ls -lsAFk' +alias lf='ls -CAFk' +alias cp='cp -p' +alias ls='ls -F' + +clock_p () { +PS1='${__[(H=SECONDS/3600%24)==(M=SECONDS/60%60)==(S=SECONDS%60)]-$H:$M:$S}>' +typeset -Z2 H M S; let SECONDS=`date '+(%H*60+%M)*60+%S'` +} +#function needed by add_path, pre_path, and del_path +no_path () { + eval _v="\$${2:-PATH}" + case \;$_v\; in + *\;$1\;*) return 1 ;; # no we have it + esac + return 0 +} +#if $1 exists and is not in path, append it, or prepend it +add_path () { + [ -d ${1:-.} ] && no_path $* && eval ${2:-PATH}="\$${2:-PATH}\;$1" +} +pre_path () { + [ -d ${1:-.} ] && no_path $* && eval ${2:-PATH}="$1\;\$${2:-PATH}" +} +#if $1 is in path then remove it +del_path () { + no_path $* || eval ${2:-PATH}=`eval print -f '\;$'${2:-PATH}'\;' | sed -e "s!;$1;!;!g" -e "s!^;!!" -e "s!;\\$!!" -e "s!;!\\\\\;!g"` +} + +unalias login newgrp + +if [ "$KSH_VERSION" = "" ] +then PS1='$PWD>' + return #bail out for sh which doesn't have edit modes +fi + +set -o emacs +bind ^Q=quote +bind ^I=complete +#bind ^[^[=list-file + +#The next four have been preprogrammed +bind ^0H=up-history +bind ^0P=down-history +bind ^0K=backward-char +bind ^0M=forward-char + +bind ^0s=backward-word +bind ^0t=forward-word +bind ^0G=beginning-of-line +bind ^0O=end-of-line +bind ^0w=beginning-of-history +bind ^0u=end-of-history +bind ^0S=eot-or-delete + + +FCEDIT=t2 +PS1='[!]$PWD: ' +function pushd { + if [ $# -eq 0 ] + then d=~ + set -A dirstk ${dirstk[*]} $PWD + cd $d + else for d in $* + do if [ -d $d ] && [ -r $d ] && [ -x $d ] + then set -A dirstk ${dirstk[*]} $PWD + cd $d + else echo "$d: Cannot change directory" + break + fi + done + fi + echo ${dirstk[*]} $PWD + unset d ; +} + +function popd { + if [ ${#dirstk[*]} -gt 0 ] + then let n=${#dirstk[*]}-1 + cd ${dirstk[$n]} + unset dirstk[$n] + echo ${dirstk[*]} $PWD + else echo "popd: Directory stack empty" + fi + unset n ; +} diff --git a/os2/make.sed b/os2/make.sed new file mode 100644 index 0000000..5905b0b --- /dev/null +++ b/os2/make.sed @@ -0,0 +1,44 @@ +s/@SHELL_PROG@/ksh/ +s!/bin/sh!sh! +s/@configure_input@/OS2_Makefile/ +s/@srcdir@/./ +s/@CC@/gcc/ +s/@CPP@/cpp/ +s/@CPPFLAGS@// +s/@INSTALL@/\/bin\/install -c/ +s/@INSTALL_PROGRAM@/$(INSTALL)/ +s/@INSTALL_DATA@/$(INSTALL) -m 644/ +s/@DEFS@/-DHAVE_CONFIG_H/ +s/@LIBS@/-los2/ +s/@LDSTATIC@// +s/@LDFLAGS@/-O -s $(LDSTATIC)/ +s/^\(CFLAGS[ ]*=\).*/\1 -O -DOS2/ +s/^\(prefix[ ]*=\).*/\1 c:\/usr/ +s/^\(exec_prefix[ ]*=\).*/\1 c:\/usr/ +s/^\(exe_suffix[ ]*=\).*/\1.exe/ +s/^\(OBJS[ ]*=\)/\1 os2.o/ +s/`echo $(SHELL_PROG)|sed '$(transform)'`/$(SHELL_PROG)/ +s#$(srcdir)/tests/th.sh#th.cmd# +/^configure:/,/^$/d +/^config.h.in:/,/^$/d +/^config.h:/,/^$/c\ +config.h:\ + cmd /c copy $(srcdir)\\os2\\config.h config.h > nul\ + touch config.h\ + +/^Makefile:/,/^$/c\ +Makefile:\ + cmd /c copy $(srcdir)\\os2\\Makefile Makefile > nul\ + touch Makefile\ + +/^config.status:/,/^$/d +/^siglist.out:/,/^$/c\ +siglist.out:\ + cmd /c copy $(srcdir)\\os2\\os2siglist.out siglist.out > nul\ + touch siglist.out\ + +/^emacs.out:/,/^$/c\ +emacs.out:\ + cmd /c copy $(srcdir)\\os2\\emacs.out emacs.out > nul\ + touch emacs.out\ + diff --git a/os2/os2.c b/os2/os2.c new file mode 100644 index 0000000..c912807 --- /dev/null +++ b/os2/os2.c @@ -0,0 +1,264 @@ +#define INCL_DOS +#define INCL_DOSERRORS +#define INCL_DOSSESMGR +#define INCL_WINPROGRAMLIST +#include +#include "config.h" +#include "sh.h" /* To get inDOS(). */ +#include +#include +#include +#include +#include +#include +#include + +static int isfullscreen(void) +{ + PTIB ptib; + PPIB ppib; + + DosGetInfoBlocks(&ptib, &ppib); + return (ppib -> pib_ultype != SSF_TYPE_WINDOWABLEVIO); +} + +static int +quoted_strlen(char *s) +{ + int ret = 0; + int seen_space = 0; + while (*s) { + if (seen_space == 0 && *s == ' ') { + ret += 2; + seen_space = 1; + } else if (*s == '\"') { + if (seen_space == 0) { + seen_space = 1; + ret += 4; + } else ret += 2; + } else ret++; + s++; + } + return ret; +} + +static char * +quoted_strcpy(char *targ, char* src) +{ + int seen_space = 0; + char *s = src, *t = targ; + + while (*s) { + if ((*s == ' ') || (*s == '\"')) { + seen_space = 1; + break; + } + s++; + } + if (seen_space) { + *targ++ = '\"'; + } + while (*src) { + if (*src == '\"') { + *targ++ = '\\'; + } + *targ++ = *src++; + } + if (seen_space) { + *targ++ = '\"'; + } + *targ = '\0'; + return t; +} + +static int +newsession(int type, int mode, char *cmd, char **args, char **env) +{ + STARTDATA sd; + STATUSDATA st; + REQUESTDATA qr; + ULONG sid, pid, len, cnt, rc; + PVOID ptr; + BYTE prio; + static char queue[18]; + static HQUEUE qid = -1; + char *ap, *ep, *p; + char object[256] = {0}; + + for ( cnt = 1, len = 0; args[cnt] != NULL; cnt++ ) + len += quoted_strlen(args[cnt]) + 1; + p = ap = alloca(len + 2); + *p = 0; + for ( cnt = 1, len = 0; args[cnt] != NULL; cnt++ ) + { + if ( cnt > 1 ) + *p++ = ' '; + quoted_strcpy(p, args[cnt]); + p += strlen(p); + } + for ( cnt = 0, len = 0; env[cnt] != NULL; cnt++ ) + len += strlen(env[cnt]) + 1; + p = ep = alloca(len + 2); + *p = 0; + for ( cnt = 0, len = 0; env[cnt] != NULL; cnt++ ) + { + strcpy(p, env[cnt]); + p += strlen(p) + 1; + } + *p = 0; + + if ( mode == P_WAIT && qid == -1 ) + { + sprintf(queue, "\\queues\\ksh%04d", getpid()); + if ( DosCreateQueue(&qid, QUE_FIFO, queue) ) + return -1; + } + + sd.Length = sizeof(sd); + sd.Related = (mode == P_WAIT) ? SSF_RELATED_CHILD : SSF_RELATED_INDEPENDENT; + sd.FgBg = SSF_FGBG_FORE; + sd.TraceOpt = SSF_TRACEOPT_NONE; + sd.PgmTitle = NULL; + sd.PgmName = cmd; + sd.PgmInputs = (PBYTE) ap; + sd.TermQ = (mode == P_WAIT) ? (PBYTE) queue : NULL; + sd.Environment = NULL; + sd.InheritOpt = SSF_INHERTOPT_PARENT; + sd.SessionType = type; + sd.IconFile = NULL; + sd.PgmHandle = 0; + sd.PgmControl = 0; + sd.Reserved = 0; + sd.ObjectBuffer = object; + sd.ObjectBuffLen = sizeof(object); + + if ( DosStartSession(&sd, &sid, &pid) ) + return errno = ENOEXEC, -1; + + if ( mode == P_WAIT ) + { + st.Length = sizeof(st); + st.SelectInd = SET_SESSION_UNCHANGED; + st.BondInd = SET_SESSION_BOND; + DosSetSession(sid, &st); + if ( DosReadQueue(qid, &qr, &len, &ptr, 0, DCWW_WAIT, &prio, 0) ) + return -1; + rc = ((PUSHORT)ptr)[1]; + DosFreeMem(ptr); + exit(rc); + } + else + exit(0); +} + +int ksh_execve(char *cmd, char **args, char **env, int flags) +{ + ULONG apptype; + char path[256], *p; + int rc; + + strcpy(path, cmd); + for ( p = path; *p; p++ ) + if ( *p == '/' ) + *p = '\\'; + + if (_emx_env & 0x1000) { /* RSX, do best we can do. */ + int len = strlen(cmd); + + if (len > 4 && stricmp(cmd + len - 4, ".bat") == 0) { + /* execve would fail anyway, but most probably segfault. */ + errno = ENOEXEC; + return -1; + } + goto do_execve; + } + + if ( inDOS() ) { + fprintf(stderr, "ksh_execve requires OS/2 or RSX!\n"); + exit(255); + } + + if ( DosQueryAppType(path, &apptype) == 0 ) + { + if (apptype & FAPPTYP_DOS) + return newsession(isfullscreen() ? SSF_TYPE_VDM : + SSF_TYPE_WINDOWEDVDM, + P_WAIT, path, args, env); + + if ((apptype & FAPPTYP_WINDOWSREAL) || + (apptype & FAPPTYP_WINDOWSPROT) || + (apptype & FAPPTYP_WINDOWSPROT31)) + return newsession(isfullscreen() ? PROG_WINDOW_AUTO : + PROG_SEAMLESSCOMMON, + P_WAIT, path, args, env); + + if ( (apptype & FAPPTYP_EXETYPE) == FAPPTYP_WINDOWAPI ) { + printf(""); /* kludge to prevent PM apps from core dumping */ + /* Start new session if interactive and not a part of a pipe. */ + return newsession(SSF_TYPE_PM, + ( (flags & XINTACT) && (flags & XPIPE) + /* _isterm(0) && _isterm(1) && _isterm(2) */ + ? P_NOWAIT + : P_WAIT), + path, args, env); + } + + if ( (apptype & FAPPTYP_EXETYPE) == FAPPTYP_NOTWINDOWCOMPAT || + (apptype & FAPPTYP_EXETYPE) == FAPPTYP_NOTSPEC ) + if ( !isfullscreen() ) + return newsession(SSF_TYPE_FULLSCREEN, + ( (flags & XINTACT) && (flags & XPIPE) + /* _isterm(0) && _isterm(1) && _isterm(2) */ + ? P_NOWAIT + : P_WAIT), + path, args, env); + } + do_execve: + { + /* P_QUOTE is too agressive, it quotes `@args_from_file' too, + which breaks emxomfld calling LINK386 when EMXSHELL=ksh. + Thus we check whether we need to quote, and delegate the hard + work to P_QUOTE if needed. */ + char **pp = args; + int do_quote = 0; + for (; !do_quote && *pp; pp++) { + for (p = *pp; *p; p++) { + if (*p == '*' || *p == '?') { + do_quote = 1; + break; + } + } + } + + if ( (rc = spawnve(P_OVERLAY | (do_quote ? P_QUOTE : 0), + path, args, env)) != -1 ) + exit(rc); + } + return -1; +} + +void UnixName(char *path) +{ + for ( ; *path; path++ ) + if ( *path == '\\' ) + *path = '/'; +} + +char *ksh_strchr_dirsep(const char *path) +{ + char *p1 = strchr(path, '\\'); + char *p2 = strchr(path, '/'); + if ( !p1 ) return p2; + if ( !p2 ) return p1; + return (p1 > p2) ? p2 : p1; +} + + +char *ksh_strrchr_dirsep(const char *path) +{ + char *p1 = strrchr(path, '\\'); + char *p2 = strrchr(path, '/'); + if ( !p1 ) return p2; + if ( !p2 ) return p1; + return (p1 > p2) ? p1 : p2; +} diff --git a/os2/os2bugs b/os2/os2bugs new file mode 100644 index 0000000..aa33424 --- /dev/null +++ b/os2/os2bugs @@ -0,0 +1,19 @@ + Bugs and Limitations + 1/99 + +1. Some of the makefile targets are not yet working. Those known to + work include all, uninstall,ksh, config.h, makefile, + debugtools (only check-fd and check-sigs.), test, clean, & distclean. + You need to run ksh Bugs ksh, or sh Bugs sh as appropriate. + +2. You cannot start a full screen session from the windowed ksh command line. + +3. Job control is not working and may never work in os/2 (no sigstp, + sigcont, etc). + +4. ls [B]* fails even when a file Bozo exists. ls [b]* will work + due to case folding. The bug is in the way case folding is managed. + ls b* or ls B* will work as expected. + +5. regress.t:regression-13 test fails. I do not understand why it can + work on *nix. In fact cat does not get SIGPIPE, but gets write failure. diff --git a/os2/os2siglist.out b/os2/os2siglist.out new file mode 100644 index 0000000..19d69d5 --- /dev/null +++ b/os2/os2siglist.out @@ -0,0 +1,24 @@ +/* + * signal handling + */ + {SIGHUP, "HUP", "Hangup"}, + {SIGINT, "INT", "Interrupt"}, + {SIGQUIT, "QUIT", "Quit"}, + {SIGILL, "ILL", "Illegal instruction"}, + {SIGTRAP, "TRAP", "Trace trap"}, + {SIGABRT, "ABRT", "Abort"}, + {SIGEMT, "EMT", "EMT trap"}, + {SIGFPE, "FPE", "Floating exception"}, + {SIGKILL, "KILL", "Killed"}, + {SIGBUS, "BUS", "Bus error"}, + {SIGSEGV, "SEGV", "Memory fault"}, + {SIGSYS, "SYS", "Bad system call"}, + {SIGPIPE, "PIPE", "Broken pipe"}, + {SIGALRM, "ALRM", "Alarm clock"}, + {SIGTERM, "TERM", "Terminated"}, + {SIGUSR1, "USR1", "User defined #1"}, + {SIGUSR2, "USR2", "User defined #2"}, + {SIGCHLD, "CHLD", "Death of a child"}, + { 19, (char *) 0, "Signal 19"}, + { 20, (char *) 0, "Signal 20"}, + {SIGBREAK, "BREAK", "Ctrl-Break"}, diff --git a/os2/th.cmd b/os2/th.cmd new file mode 100644 index 0000000..af15874 --- /dev/null +++ b/os2/th.cmd @@ -0,0 +1,28 @@ +extproc ksh +# +# Simple script to find perl and run it +# for os2 + +IFS=\;$IFS +perl= +for i in $PATH; do + [ X"$i" = X ] && i=. + for j in perl perl5x perl5 ; do + [ -x $i/$j.exe ] && perl=$i/$j.exe && break 2 + done +done + +[ X"$perl" = X ] && { + echo "$0: can't find perl - bye\n" 1>&2 + exit 1 + } + +perlpath=`dirname $perl` +if [ `basename $perlpath` = bin ] +then perlpath=`dirname $perlpath` +fi +if [ "$PERL5LIB" = "" ] +then PERL5LIB=$perlpath/lib +fi +export PERL5LIB +exec $perl "$@" diff --git a/sigact.c b/sigact.c new file mode 100644 index 0000000..8e12af0 --- /dev/null +++ b/sigact.c @@ -0,0 +1,482 @@ +/* NAME: + * sigact.c - fake sigaction(2) + * + * SYNOPSIS: + * #include "sigact.h" + * + * int sigaction(int sig, struct sigaction *act, + * struct sigaction *oact); + * int sigaddset(sigset_t *mask, int sig); + * int sigdelset(sigset_t *mask, int sig); + * int sigemptyset(sigset_t *mask); + * int sigfillset(sigset_t *mask); + * int sigismember(sigset_t *mask, int sig); + * int sigpending(sigset_t *set); + * int sigprocmask(int how, sigset_t *set, sigset_t *oset); + * int sigsuspend(sigset_t *mask); + * + * RETSIGTYPE (*Signal(int sig, RETSIGTYPE (*disp)(int)))(int); + * + * DESCRIPTION: + * This is a fake sigaction implementation. It uses + * sigsetmask(2) et al or sigset(2) and friends if + * available, otherwise it just uses signal(2). If it + * thinks sigaction(2) really exists it compiles to "almost" + * nothing. + * + * In any case it provides a Signal() function that is + * implemented in terms of sigaction(). + * If not using signal(2) as part of the underlying + * implementation (USE_SIGNAL or USE_SIGMASK), and + * NO_SIGNAL is not defined, it also provides a signal() + * function that calls Signal(). + * + * The need for all this mucking about is the problems + * caused by mixing various signal handling mechanisms in + * the one process. This module allows for a consistent + * POSIX compliant interface to whatever is actually + * available. + * + * sigaction() allows the caller to examine and/or set the + * action to be associated with a given signal. "act" and + * "oact" are pointers to 'sigaction structs': + *.nf + * + * struct sigaction + * { + * RETSIGTYPE (*sa_handler)(); + * sigset_t sa_mask; + * int sa_flags; + * }; + *.fi + * + * RETSIGTYPE is normally 'void' in the POSIX implementation + * and for most current systems. On some older UNIX + * systems, signal handlers do not return 'void', so + * this implementation keeps 'sa_handler' inline with the + * hosts normal signal handling conventions. + * 'sa_mask' controls which signals will be blocked while + * the selected signal handler is active. It is not used + * in this implementation. + * 'sa_flags' controls various semantics such as whether + * system calls should be automagically restarted + * (SA_RESTART) etc. It is not used in this + * implementation. + * Either "act" or "oact" may be NULL in which case the + * appropriate operation is skipped. + * + * sigaddset() adds "sig" to the sigset_t pointed to by "mask". + * + * sigdelset() removes "sig" from the sigset_t pointed to + * by "mask". + * + * sigemptyset() makes the sigset_t pointed to by "mask" empty. + * + * sigfillset() makes the sigset_t pointed to by "mask" + * full ie. match all signals. + * + * sigismember() returns true if "sig" is found in "*mask". + * + * sigpending() is supposed to return "set" loaded with the + * set of signals that are blocked and pending for the + * calling process. It does nothing in this impementation. + * + * sigprocmask() is used to examine and/or change the + * signal mask for the calling process. Either "set" or + * "oset" may be NULL in which case the appropriate + * operation is skipped. "how" may be one of SIG_BLOCK, + * SIG_UNBLOCK or SIG_SETMASK. If this package is built + * with USE_SIGNAL, then this routine achieves nothing. + * + * sigsuspend() sets the signal mask to "*mask" and waits + * for a signal to be delivered after which the previous + * mask is restored. + * + * + * RETURN VALUE: + * 0==success, -1==failure + * + * BUGS: + * Since we fake most of this, don't expect fancy usage to + * work. + * + * AUTHOR: + * Simon J. Gerraty + */ +/* COPYRIGHT: + * @(#)Copyright (c) 1992 Simon J. Gerraty + * + * 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. + * + * Please send copies of changes and bug-fixes to: + * sjg@zen.void.oz.au + * + */ +/* Changes to sigact.c for pdksh, Michael Rendell : + * - sigsuspend(): pass *mask to bsd4.2 sigpause instead of mask. + * - changed SIG_HDLR to RETSIGTYPE for use with GNU autoconf + * - added and used RETSIGVAL + * - include sh.h instead of signal.h (to get *_SIGNALS macros) + * - changed if !SA_NOCLDSTOP ... to USE_FAKE_SIGACT to avoid confusion + * - set the USE_* defines using the *_SIGNALS defines from autoconf + * - sigaction(): if using BSD signals, use sigvec() (used to use + * signal()) and set the SV_INTERRUPT flag (POSIX says syscalls + * are interrupted and pdksh needs this behaviour). + * - define IS_KSH before including anything; ifdef out routines + * not used in ksh if IS_KSH is defined (same in sigact.h). + * - use ARGS() instead of __P() + * - sigaction(),sigsuspend(),Signal(),signal(): use handler_t typedef + * instead of explicit type. + */ + +/* + #include +*/ +#define IS_KSH +#include "sh.h" + +/* + #ifndef __P + # if defined(__STDC__) || defined(__cplusplus) + # define __P(p) p + # else + # define __P(p) () + # endif + #endif +*/ + + +/* + * some systems have a faulty sigaction() implementation! + * Allow us to bypass it. + * Or they may have installed sigact.h as signal.h which is why + * we have SA_NOCLDSTOP defined. + */ +#ifdef USE_FAKE_SIGACT /* let autoconf decide.. */ +/* #if !defined(SA_NOCLDSTOP) || defined(_SIGACT_H) || defined(USE_SIGNAL) || defined(USE_SIGSET) || defined(USE_SIGMASK) */ + +/* Let autoconf decide which to use */ +#ifdef BSD42_SIGNALS +# define USE_SIGMASK +#else +# ifdef BSD41_SIGNALS +# define USE_SIGSET +# else +# define USE_SIGNAL +# endif +#endif /* BSD42_SIGNALS */ + +/* + * if we haven't been told, + * try and guess what we should implement with. + */ +#if !defined(USE_SIGSET) && !defined(USE_SIGMASK) && !defined(USE_SIGNAL) +# if defined(sigmask) || defined(BSD) || defined(_BSD) && !defined(BSD41) +# define USE_SIGMASK +# else +# ifndef NO_SIGSET +# define USE_SIGSET +# else +# define USE_SIGNAL +# endif +# endif +#endif +/* + * if we still don't know, we're in trouble + */ +#if !defined(USE_SIGSET) && !defined(USE_SIGMASK) && !defined(USE_SIGNAL) +error must know what to implement with +#endif + +#include "sigact.h" + +/* + * in case signal() has been mapped to our Signal(). + */ +#undef signal + + +int +sigaction(sig, act, oact) + int sig; + struct sigaction *act, *oact; +{ + handler_t oldh; + + if (act) + { +#ifdef USE_SIGSET + oldh = sigset(sig, act->sa_handler); +#else +# ifdef USE_SIGMASK + struct sigvec nsv,osv; + + nsv.sv_handler = act->sa_handler; + nsv.sv_mask = 0; /* punt */ + nsv.sv_flags = SV_INTERRUPT; /* punt */ + sigvec(sig, &nsv, &osv); + oldh = osv.sv_handler; +# else /* USE_SIGMASK */ + oldh = signal(sig, act->sa_handler); +# endif /* USE_SIGMASK */ +#endif + } + else + { + if (oact) + { +#ifdef USE_SIGSET + oldh = sigset(sig, SIG_IGN); +#else + oldh = signal(sig, SIG_IGN); +#endif + if (oldh != SIG_IGN && oldh != SIG_ERR) + { +#ifdef USE_SIGSET + (void) sigset(sig, oldh); +#else + (void) signal(sig, oldh); +#endif + } + } + } + if (oact) + { + oact->sa_handler = oldh; + } + return 0; /* hey we're faking it */ +} + + +int +sigaddset(mask, sig) + sigset_t *mask; + int sig; +{ + *mask |= sigmask(sig); + return 0; +} + + +#ifndef IS_KSH +int +sigdelset(mask, sig) + sigset_t *mask; + int sig; +{ + *mask &= ~(sigmask(sig)); + return 0; +} +#endif /* IS_KSH */ + + +int +sigemptyset(mask) + sigset_t *mask; +{ + *mask = 0; + return 0; +} + + +#ifndef IS_KSH +int +sigfillset(mask) + sigset_t *mask; +{ + *mask = ~0; + return 0; +} +#endif /* IS_KSH */ + + +#ifndef IS_KSH +int +sigismember(mask, sig) + sigset_t *mask; + int sig; +{ + return ((*mask) & sigmask(sig)); +} +#endif /* IS_KSH */ + + +#ifndef IS_KSH +int +sigpending(set) + sigset_t *set; +{ + return 0; /* faking it! */ +} +#endif /* IS_KSH */ + + +int +sigprocmask(how, set, oset) + int how; + sigset_t *set, *oset; +{ +#ifdef USE_SIGSET + register int i; +#endif + static sigset_t sm; + static int once = 0; + + if (!once) + { + /* + * initally we clear sm, + * there after, it represents the last + * thing we did. + */ + once++; +#ifdef USE_SIGMASK + sm = sigblock(0); +#else + sm = 0; +#endif + } + + if (oset) + *oset = sm; + if (set) + { + switch (how) + { + case SIG_BLOCK: + sm |= *set; + break; + case SIG_UNBLOCK: + sm &= ~(*set); + break; + case SIG_SETMASK: + sm = *set; + break; + } +#ifdef USE_SIGMASK + (void) sigsetmask(sm); +#else +# ifdef USE_SIGSET + for (i = 1; i < NSIG; i++) + { + if (how == SIG_UNBLOCK) + { + if (*set & sigmask(i)) + sigrelse(i); + } + else + if (sm & sigmask(i)) + { + sighold(i); + } + } +# endif +#endif + } + return 0; +} + + +int +sigsuspend(mask) + sigset_t *mask; +{ +#ifdef USE_SIGMASK + sigpause(*mask); +#else + register int i; + +# ifdef USE_SIGSET + + for (i = 1; i < NSIG; i++) + { + if (*mask & sigmask(i)) + { + /* not the same sigpause() as above! */ + sigpause(i); + break; + } + } +# else /* signal(2) only */ + handler_t oldh; + + /* + * make sure that signals in mask will not + * be ignored. + */ + for (i = 1; i < NSIG; i++) + { + if (*mask & sigmask(i)) + { + if ((oldh = signal(i, SIG_DFL)) != SIG_ERR && + oldh != SIG_IGN && + oldh != SIG_DFL) + (void) signal(i, oldh); /* restore handler */ + } + } + pause(); /* wait for a signal */ +# endif +#endif + return 0; +} + +#endif /* USE_FAKE_SIGACT (was ! SA_NOCLDSTOP) */ + +#if !defined(RETSIGTYPE) +# define RETSIGTYPE void +# define RETSIGVAL +#endif +#if !defined(SIG_ERR) +# define SIG_ERR (RETSIGTYPE (*)())-1 +#endif + +/* + * an implementation of signal() using sigaction(). + */ + +#ifndef IS_KSH +handler_t Signal(sig, handler) + int sig; + handler_t handler; +{ + struct sigaction act, oact; + + act.sa_handler = handler; + sigemptyset(&act.sa_mask); + act.sa_flags = 0; + if (sigaction(sig, &act, &oact) < 0) + return (SIG_ERR); + return (oact.sa_handler); +} +#endif /* IS_KSH */ + +#ifndef IS_KSH +#if !defined(USE_SIGNAL) && !defined(USE_SIGMASK) && !defined(NO_SIGNAL) +/* + * ensure we avoid signal mayhem + */ + +handler_t signal(sig, handler) + int sig; + handler_t handler; +{ + return (Signal(sig, handler)); +} +#endif +#endif /* IS_KSH */ + +/* This lot (for GNU-Emacs) goes at the end of the file. */ +/* + * Local Variables: + * version-control:t + * comment-column:40 + * End: + */ diff --git a/sigact.h b/sigact.h new file mode 100644 index 0000000..b3d6081 --- /dev/null +++ b/sigact.h @@ -0,0 +1,129 @@ +/* NAME: + * sigact.h - sigaction et al + * + * SYNOPSIS: + * #include "sigact.h" + * + * DESCRIPTION: + * This header is the interface to a fake sigaction(2) + * implementation. It provides a POSIX compliant interface + * to whatever signal handling mechanisms are available. + * It also provides a Signal() function that is implemented + * in terms of sigaction(). + * If not using signal(2) as part of the underlying + * implementation (USE_SIGNAL or USE_SIGMASK), and + * NO_SIGNAL is not defined, it also provides a signal() + * function that calls Signal(). + * + * SEE ALSO: + * sigact.c + */ +/* + * RCSid: + * $Id: sigact.h,v 1.1 2004/03/21 00:34:16 tg Exp $ + */ +/* Changes to sigact.h for pdksh, Michael Rendell : + * - changed SIG_HDLR to RETSIGTYPE for use with GNU autoconf + * - added RETSIGVAL + * - ifdef'd out ARGS(), volatile and const initializations + * - ifdef'd out sigset_t definition - let autoconf handle it + * - ifdef out routines not used in ksh if IS_KSH is defined + * (same in sigact.c). + */ +#ifndef _SIGACT_H +#define _SIGACT_H + +/* + * most modern systems use void for signal handlers but + * not all. + */ +#ifndef RETSIGTYPE +# define RETSIGTYPE void +# define RETSIGVAL +#endif + +#if 0 /* ARGS(), volatile and const are already set up in config*.h -mhr */ +#undef ARGS +#if defined(__STDC__) || defined(__cplusplus) +# define ARGS(p) p +#else +# define ARGS(p) () +# define volatile /* don't optimize please */ +# define const /* read only */ +#endif +#endif + +#ifndef IS_KSH +handler_t Signal ARGS((int sig, handler_t disp)); +#endif /* IS_KSH */ + +/* + * if you want to install this header as signal.h, + * modify this to pick up the original signal.h + */ +#ifndef SIGKILL +# include +#endif + +#ifndef SIG_ERR +# define SIG_ERR ((handler_t) -1) +#endif +#ifndef BADSIG +# define BADSIG SIG_ERR +#endif + +#ifndef SA_NOCLDSTOP +/* we assume we need the fake sigaction */ +/* sa_flags */ +#define SA_NOCLDSTOP 1 /* don't send SIGCHLD on child stop */ +#define SA_RESTART 2 /* re-start I/O */ + +/* sigprocmask flags */ +#define SIG_BLOCK 1 +#define SIG_UNBLOCK 2 +#define SIG_SETMASK 4 + +#if 0 /* autoconf will define sigset_t if it isn't available */ +/* + * this is a bit untidy + */ +#if !defined(__sys_stdtypes_h) +typedef unsigned int sigset_t; +#endif +#endif /* 0 */ + +/* + * POSIX sa_handler should return void, but since we are + * implementing in terms of something else, it may + * be appropriate to use the normal RETSIGTYPE return type + */ +struct sigaction +{ + handler_t sa_handler; + sigset_t sa_mask; + int sa_flags; +}; + + +int sigaction ARGS(( int sig, struct sigaction *act, struct sigaction *oact )); +int sigaddset ARGS(( sigset_t *mask, int sig )); +#ifndef IS_KSH +int sigdelset ARGS(( sigset_t *mask, int sig )); +#endif /* IS_KSH */ +int sigemptyset ARGS(( sigset_t *mask )); +#ifndef IS_KSH +int sigfillset ARGS(( sigset_t *mask )); +int sigismember ARGS(( sigset_t *mask, int sig )); +int sigpending ARGS(( sigset_t *set )); +#endif /* IS_KSH */ +int sigprocmask ARGS(( int how, sigset_t *set, sigset_t *oset )); +int sigsuspend ARGS(( sigset_t *mask )); + +#ifndef sigmask +# define sigmask(s) (1<<((s)-1)) /* convert SIGnum to mask */ +#endif +#if !defined(NSIG) && defined(_NSIG) +# define NSIG _NSIG +#endif +#endif /* ! SA_NOCLDSTOP */ +#endif /* _SIGACT_H */ diff --git a/stamp-h.in b/stamp-h.in new file mode 100644 index 0000000..62b5832 --- /dev/null +++ b/stamp-h.in @@ -0,0 +1 @@ +Tue Apr 20 17:32:21 NDT 1999