diff --git a/NEWS b/NEWS index 0348b5174..c625356c7 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,18 @@ For full details, see the git log at: https://github.com/ksh93/ksh Any uppercase BUG_* names are modernish shell bug IDs. +2020-09-01: + +- The bash-style '&>file' redirection shorthand (for '>file 2>&1') is now + always recognised and not only when running rc/profile init scripts. It no + longer issues a warning. This brings ksh93 in line with mksh, bash and zsh. + +- A long-form shell option '-o posix' has been added, which implements a + mode for better compatibility with the POSIX standard. It is automatically + turned on if ksh is invoked under the name 'sh'. + For now, it: + * disables the &> redirection shorthand + 2020-08-19: - Sped up the 'read' command on most systems by 15-25%. Fixed a hanging bug diff --git a/src/cmd/ksh93/DESIGN b/src/cmd/ksh93/DESIGN index 2c621767b..6d10a3f1b 100644 --- a/src/cmd/ksh93/DESIGN +++ b/src/cmd/ksh93/DESIGN @@ -43,10 +43,6 @@ Directory layout: fixes and new features since the original ksh93 release. The file COMPATIBILITY is a list of all known incompatibilities with ksh88. - The data/bash_pre_rc.sh is a startup script used when emulating - bash if the shell is compiled with SHOPT_BASH and the shell - is invoked as bash. The bash emulation is not complete. - Include directory: 1. argnod.h contains the type definitions for command nodes, io nodes, argument nodes, and for positional @@ -111,8 +107,7 @@ sh directory: library and the interface to shell arithmetic. 3. array.c contains the code for indexed and associative arrays. - 4. bash.c contains code used when compiling with SHOPT_BASH - to add bash specific features such as shopt. + 4. (removed) 5. defs.c contains the data definitions for global symbols. 6. deparse.c contains code to generate shell script from a parse tree. diff --git a/src/cmd/ksh93/Makefile b/src/cmd/ksh93/Makefile index e57fcb662..095987757 100644 --- a/src/cmd/ksh93/Makefile +++ b/src/cmd/ksh93/Makefile @@ -20,7 +20,6 @@ SHOPT_ACCT == /* accounting */ SHOPT_ACCTFILE == /* per user accounting info */ SHOPT_AUDIT == 1 /* enable auditing per SHOPT_AUDITFILE */ SHOPT_AUDITFILE == "/etc/ksh_audit" /* auditing file */ -SHOPT_BASH == /* bash compatibility code */ SHOPT_BGX == 1 /* one SIGCHLD trap per completed job */ SHOPT_BRACEPAT == 1 /* C-shell {...,...} expansions (, required) */ SHOPT_CMDLIB_HDR == /* -lcmd builtin list () */ @@ -98,11 +97,6 @@ if CC.HOSTTYPE == "win32*" SHOPT_CRNL == 1 /* is equivalent to */ end -if SHOPT_BASH - BASH_HOSTTYPE == "$(CC.HOSTTYPE:S:/\.//)" - BASH_MACHTYPE == "$(BASH_HOSTTYPE)-unknown-$(CC.HOSTTYPE:B)" -end - /* use the following libraries only if they exist */ LIBS_opt := +ljobs +li @@ -136,10 +130,6 @@ end if SHOPT_VSH FILES_opt += vi.c end -if SHOPT_BASH - FILES_opt += bash.c bash_pre_rc.c - SHOPT_HISTEXPAND == 1 -end if SHOPT_HISTEXPAND FILES_opt += hexpand.c end @@ -150,7 +140,7 @@ if SHOPT_X LDFLAGS += -u _XtAppInitialize -L/usr/add-on/X11/lib end -:ALL: $(SH) $(SHCOMP) $(SHOPT_SUID_EXEC:+suid_exec) $(SHOPT_BASH:+bash$(RELEASE)) +:ALL: $(SH) $(SHCOMP) $(SHOPT_SUID_EXEC:+suid_exec) $(SH) :: sh.1 pmain.c $(LIBS_req) @@ -191,19 +181,8 @@ $(FUNDIR) :INSTALLDIR: mode=+x dirs popd pushd shcomp.o : _BLD_DLL= $(CC.HOSTTYPE:N=cygwin.*:??_BLD_shell=?) -if SHOPT_BASH - -bash$(RELEASE) :LINK: $(SH) - -bash_pre_rc.c : bash_pre_rc.sh - echo "const char bash_pre_rc[] = " > $(<) - sed -e 's/\\/\\\\/g' -e 's/"/\\"/g' -e 's/'"'"'/\\'"'"'/g' -e 's/^[[:space:]]*\(.*\)$/\"\1\\n\"/' $(*) >> $(<) - echo ";" >> $(<) - -end - :: math.tab syscall.s mamexec mamstate.c $(DOCFILES) \ - bash.c bash_pre_rc.sh hexpand.c mkservice.c \ + hexpand.c mkservice.c \ shopen.mk shopen.c :: shtests \ diff --git a/src/cmd/ksh93/Mamfile b/src/cmd/ksh93/Mamfile index af797b7fd..7baf0b285 100644 --- a/src/cmd/ksh93/Mamfile +++ b/src/cmd/ksh93/Mamfile @@ -645,7 +645,7 @@ prev ${PACKAGE_ast_INCLUDE}/ast.h implicit done sh/main.c meta main.o %.c>%.o sh/main.c main prev sh/main.c -exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${-debug-symbols?1?${mam_cc_DEBUG} -D_BLD_DEBUG?${CCFLAGS.FORCE}?} ${DEBUG+-DDEBUG=${DEBUG}} ${SHOPT_TIMEOUT+-DSHOPT_TIMEOUT=${SHOPT_TIMEOUT}} ${SHOPT_ACCT+-DSHOPT_ACCT=${SHOPT_ACCT}} ${SH_DICT+-DSH_DICT=${SH_DICT}} ${SHOPT_SYSRC+-DSHOPT_SYSRC=${SHOPT_SYSRC}} ${SHOPT_BASH+-DSHOPT_BASH=${SHOPT_BASH}} ${SHOPT_REMOTE+-DSHOPT_REMOTE=${SHOPT_REMOTE}} ${SHOPT_OLDTERMIO+-DSHOPT_OLDTERMIO=${SHOPT_OLDTERMIO}} ${SHOPT_SPAWN+-DSHOPT_SPAWN=${SHOPT_SPAWN}} ${SH_CMDLIB_DIR+-DSH_CMDLIB_DIR=${SH_CMDLIB_DIR}} ${SHOPT_P_SUID+-DSHOPT_P_SUID=${SHOPT_P_SUID}} ${SHOPT_REGRESS+-DSHOPT_REGRESS=${SHOPT_REGRESS}} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_BRACEPAT -D_API_ast=20100309 -D_PACKAGE_ast -DSHOPT_ESH -D_BLD_shell -DSHOPT_KIA -DSHOPT_MULTIBYTE -DSHOPT_PFSH -DSHOPT_BGX -DKSHELL -DSHOPT_SUID_EXEC -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_HISTEXPAND -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -DSHOPT_DYNAMIC -c sh/main.c +exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${-debug-symbols?1?${mam_cc_DEBUG} -D_BLD_DEBUG?${CCFLAGS.FORCE}?} ${DEBUG+-DDEBUG=${DEBUG}} ${SHOPT_TIMEOUT+-DSHOPT_TIMEOUT=${SHOPT_TIMEOUT}} ${SHOPT_ACCT+-DSHOPT_ACCT=${SHOPT_ACCT}} ${SH_DICT+-DSH_DICT=${SH_DICT}} ${SHOPT_SYSRC+-DSHOPT_SYSRC=${SHOPT_SYSRC}} ${SHOPT_REMOTE+-DSHOPT_REMOTE=${SHOPT_REMOTE}} ${SHOPT_OLDTERMIO+-DSHOPT_OLDTERMIO=${SHOPT_OLDTERMIO}} ${SHOPT_SPAWN+-DSHOPT_SPAWN=${SHOPT_SPAWN}} ${SH_CMDLIB_DIR+-DSH_CMDLIB_DIR=${SH_CMDLIB_DIR}} ${SHOPT_P_SUID+-DSHOPT_P_SUID=${SHOPT_P_SUID}} ${SHOPT_REGRESS+-DSHOPT_REGRESS=${SHOPT_REGRESS}} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_BRACEPAT -D_API_ast=20100309 -D_PACKAGE_ast -DSHOPT_ESH -D_BLD_shell -DSHOPT_KIA -DSHOPT_MULTIBYTE -DSHOPT_PFSH -DSHOPT_BGX -DKSHELL -DSHOPT_SUID_EXEC -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_HISTEXPAND -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -DSHOPT_DYNAMIC -c sh/main.c done main.o generated make nvdisc.o make sh/nvdisc.c @@ -1101,7 +1101,7 @@ prev include/defs.h implicit done sh/trestore.c meta trestore.o %.c>%.o sh/trestore.c trestore prev sh/trestore.c -exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${-debug-symbols?1?${mam_cc_DEBUG} -D_BLD_DEBUG?${CCFLAGS.FORCE}?} ${SHOPT_BASH+-DSHOPT_BASH=${SHOPT_BASH}} ${SHOPT_SYSRC+-DSHOPT_SYSRC=${SHOPT_SYSRC}} ${SHOPT_ACCT+-DSHOPT_ACCT=${SHOPT_ACCT}} ${SHOPT_SPAWN+-DSHOPT_SPAWN=${SHOPT_SPAWN}} ${SH_CMDLIB_DIR+-DSH_CMDLIB_DIR=${SH_CMDLIB_DIR}} ${SH_DICT+-DSH_DICT=${SH_DICT}} ${SHOPT_P_SUID+-DSHOPT_P_SUID=${SHOPT_P_SUID}} ${SHOPT_REGRESS+-DSHOPT_REGRESS=${SHOPT_REGRESS}} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -D_BLD_shell -DKSHELL -D_API_ast=20100309 -D_PACKAGE_ast -DSHOPT_SUID_EXEC -DSHOPT_BRACEPAT -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_PFSH -DSHOPT_HISTEXPAND -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -DSHOPT_ESH -DSHOPT_MULTIBYTE -c sh/trestore.c +exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${-debug-symbols?1?${mam_cc_DEBUG} -D_BLD_DEBUG?${CCFLAGS.FORCE}?} ${SHOPT_SYSRC+-DSHOPT_SYSRC=${SHOPT_SYSRC}} ${SHOPT_ACCT+-DSHOPT_ACCT=${SHOPT_ACCT}} ${SHOPT_SPAWN+-DSHOPT_SPAWN=${SHOPT_SPAWN}} ${SH_CMDLIB_DIR+-DSH_CMDLIB_DIR=${SH_CMDLIB_DIR}} ${SH_DICT+-DSH_DICT=${SH_DICT}} ${SHOPT_P_SUID+-DSHOPT_P_SUID=${SHOPT_P_SUID}} ${SHOPT_REGRESS+-DSHOPT_REGRESS=${SHOPT_REGRESS}} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -D_BLD_shell -DKSHELL -D_API_ast=20100309 -D_PACKAGE_ast -DSHOPT_SUID_EXEC -DSHOPT_BRACEPAT -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_PFSH -DSHOPT_HISTEXPAND -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -DSHOPT_ESH -DSHOPT_MULTIBYTE -c sh/trestore.c done trestore.o generated make waitevent.o make sh/waitevent.c @@ -1189,7 +1189,7 @@ prev ${PACKAGE_ast_INCLUDE}/ast_standards.h implicit done data/strdata.c meta strdata.o %.c>%.o data/strdata.c strdata prev data/strdata.c -exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${-debug-symbols?1?${mam_cc_DEBUG} -D_BLD_DEBUG?${CCFLAGS.FORCE}?} ${SHOPT_BASH+-DSHOPT_BASH=${SHOPT_BASH}} ${SH_CMDLIB_DIR+-DSH_CMDLIB_DIR=${SH_CMDLIB_DIR}} ${SH_DICT+-DSH_DICT=${SH_DICT}} ${SHOPT_P_SUID+-DSHOPT_P_SUID=${SHOPT_P_SUID}} ${SHOPT_REGRESS+-DSHOPT_REGRESS=${SHOPT_REGRESS}} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_PFSH -DSHOPT_HISTEXPAND -D_BLD_shell -D_API_ast=20100309 -D_PACKAGE_ast -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -DSHOPT_ESH -DSHOPT_MULTIBYTE -c data/strdata.c +exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${-debug-symbols?1?${mam_cc_DEBUG} -D_BLD_DEBUG?${CCFLAGS.FORCE}?} ${SH_CMDLIB_DIR+-DSH_CMDLIB_DIR=${SH_CMDLIB_DIR}} ${SH_DICT+-DSH_DICT=${SH_DICT}} ${SHOPT_P_SUID+-DSHOPT_P_SUID=${SHOPT_P_SUID}} ${SHOPT_REGRESS+-DSHOPT_REGRESS=${SHOPT_REGRESS}} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_PFSH -DSHOPT_HISTEXPAND -D_BLD_shell -D_API_ast=20100309 -D_PACKAGE_ast -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -DSHOPT_ESH -DSHOPT_MULTIBYTE -c data/strdata.c done strdata.o generated make testops.o make data/testops.c diff --git a/src/cmd/ksh93/data/bash_pre_rc.sh b/src/cmd/ksh93/data/bash_pre_rc.sh deleted file mode 100644 index 4f8a451ea..000000000 --- a/src/cmd/ksh93/data/bash_pre_rc.sh +++ /dev/null @@ -1,255 +0,0 @@ -######################################################################## -# # -# This software is part of the ast package # -# Copyright (c) 1982-2011 AT&T Intellectual Property # -# and is licensed under the # -# Eclipse Public License, Version 1.0 # -# by AT&T Intellectual Property # -# # -# A copy of the License is available at # -# http://www.eclipse.org/org/documents/epl-v10.html # -# (with md5 checksum b35adb5213ca9657e911e9befb180842) # -# # -# Information and Software Systems Research # -# AT&T Research # -# Florham Park NJ # -# # -# David Korn # -# # -######################################################################## -# -# bash compatibility startup script -# -# Author: -# Karsten Fleischer -# Omnium Software Engineering -# An der Luisenburg 7 -# D-51379 Leverkusen -# Germany -# -# -# - -alias declare=typeset - -nameref FUNCNAME=.sh.fun -integer SHLVL -export SHLVL -SHLVL+=1 - -if [[ ! $EUID ]] -then EUID=$(id -u) - readonly EUID -fi - -if [[ ! $UID ]] -then UID=$(id -u) - readonly UID -fi - -readonly SHELLOPTS -if ! shopt -qo restricted; then - IFS=: - for i in $SHELLOPTS - do - [[ -n "$i" ]] && set -o $i - done - unset IFS -fi -function SHELLOPTS.get -{ - .sh.value=$(shopt -so) - .sh.value=${.sh.value//+([[:space:]])on*([[:space:]])/:} - .sh.value=${.sh.value%:} -} - -set -A GROUPS $(id -G) -function GROUPS.set -{ - return 1 -} -function GROUPS.unset -{ - unset -f GROUPS.set - unset -f GROUPS.unset -} - -typeset -A DIRSTACK -function DIRSTACK.get -{ - set -A .sh.value $(dirs) -} -function DIRSTACK.set -{ - integer index - index=_push_max-.sh.subscript - (( index == _push_max || index < _push_top )) && return - _push_stack[index]=${.sh.value} -} -function DIRSTACK.unset -{ - unset -f DIRSTACK.get - unset -f DIRSTACK.set - unset -f DIRSTACK.unset -} - -function PS1.set -{ - typeset prefix remaining=${.sh.value} var= n= k= - while [[ $remaining ]] - do prefix=${remaining%%'\'*} - remaining=${remaining#$prefix} - var+="$prefix" - case ${remaining:1:1} in - t) var+="\$(printf '%(%H:%M:%S)T')";; - d) var+="\$(printf '%(%a %b:%e)T')";; - n) var+=$'\n';; - s) var+=ksh;; - w) var+="\$(pwd)";; - W) var+="\$(basename \"\$(pwd)\")";; - u) var+=$USER;; - h) var+=$(hostname -s);; - '#') var+=!;; - !) var+=!;; - @) var+="\$(printf '%(%I:%M%p)T')";; - '$') if (( $(id -u) == 0 )) - then var+='#' - else var+='$' - fi;; - '\') var+='\\';; - '['|']') ;; - [0-7]) case ${remaining:1:3} in - [0-7][0-7][0-7]) - k=4;; - [0-7][0-7]) - k=3;; - *) k=2;; - esac - eval n="\$'"${remaining:0:k}"'" - var+=$n - remaining=${remaining:k} - continue - ;; - "") ;; - *) var+='\'${remaining:0:2};; - esac - remaining=${remaining:2} - done - .sh.value=$var -} -function logout -{ - if shopt -q login_shell; then - exit - else - print ${BASH##*/}: $0: not login shell: use 'exit' >&2 - return 1 - fi -} -PS1="bash$ " - -function source -{ - if ! shopt -qpo posix; then - unset OPATH - typeset OPATH=$PATH - typeset PATH=$PATH - if shopt -q sourcepath; then - PATH=$OPATH:. - else - PATH=. - fi - fi - . "$@" -} -unalias . -alias .=source - -alias enable=builtin - -function help -{ - typeset b cmd usage try_cmd man - function has_help_option - { - [[ $1 == @(''|/*|:|echo|false|true|login|test|'[') ]] && return 1 - return 0 - } - typeset -A short_use=( - [echo]='Usage: echo [ options ] [arg]...' - [:]='Usage: : ...' - [true]='Usage: true ...' - [false]='Usage: false ...' - [login]='Usage: login [-p] [name]' - ['[']='Usage: [ EXPRESSION ] | [ OPTION' - [test]='Usage: test EXPRESSION | test' - ) - b=$(builtin) - if (( $# == 0)) - then print 'The following is the current list of built-in commands:' - print -r $'Type help *name* for more information about name\n' - for cmd in $b - do if has_help_option $cmd - then usage=$($cmd --short 2>&1) - print -r -- "${usage:7}" - else print -r -- ${short_use[$cmd]:7} - fi - done - return - fi - b=${b/'['/} - man=--man - [[ $1 == -s ]] && man=--short && shift - for try_cmd - do if has_help_option $try_cmd - then if [[ $try_cmd == @(${b//$'\n'/'|'}) ]] - then $try_cmd $man - else man $try_cmd - fi - elif [[ $man == '--short' ]] - then print -r -- ${short_use[$try_cmd]} - else man $try_cmd - fi - done -} - -function cd -{ - - local msg - local args - local i - local a - local ret - - if ! shopt -q cdable_vars; then - command cd "$@" - else - msg=$(command cd "$@" 2>&1) - ret=$? - if [[ $ret != 0 ]]; then - for i - do - case $i in - -*) args="$args $i" ;; - */*) args="$args $i" ;; - *) eval a="$"$i - if [[ -n $a ]]; then args="$args $a" - else args="$args $i" - fi - ;; - esac - done - - command cd $args - else - print -- $msg - return $ret - fi - fi -} - -typeset BASH=$0 -! shopt -qo posix && HISTFILE=~/.bash_history -HOSTNAME=$(hostname) -nameref BASH_SUBSHELL=.sh.subshell diff --git a/src/cmd/ksh93/data/builtins.c b/src/cmd/ksh93/data/builtins.c index a68f82ef8..c39e363f5 100644 --- a/src/cmd/ksh93/data/builtins.c +++ b/src/cmd/ksh93/data/builtins.c @@ -54,7 +54,6 @@ /* * IMPORTANT: The order of these struct members must be synchronous * with the offsets on the macros defined in include/builtins.h! - * The order up through "local" is significant. */ const struct shtable3 shtab_builtins[] = { @@ -81,9 +80,6 @@ const struct shtable3 shtab_builtins[] = ".", NV_BLTIN|BLT_ENV|BLT_SPC, bltin(dot_cmd), "source", NV_BLTIN|BLT_ENV, bltin(dot_cmd), "return", NV_BLTIN|BLT_ENV|BLT_SPC, bltin(return), -#if SHOPT_BASH - "local", NV_BLTIN|BLT_ENV|BLT_SPC|BLT_DCL,bltin(typeset), -#endif /* * Builtins without offset macros in include/builtins.h follow. */ @@ -220,13 +216,6 @@ const char sh_set[] = "[+gmacs?Enables/disables \bgmacs\b editing mode. \bgmacs\b " "editing mode is the same as \bemacs\b editing mode " "except for the handling of \b^T\b.]" -#if SHOPT_BASH - "[+hashall?Equivalent to \b-h\b and \b-o trackall\b. Available " - "in bash compatibility mode only.]" - "[+history?Enable command history. Available in bash " - "compatibility mode only. On by default in interactive " - "shells.]" -#endif #if SHOPT_HISTEXPAND "[+histexpand?Equivalent to \b-H\b.]" #endif @@ -247,20 +236,12 @@ const char sh_set[] = "compatibility.]" "[+notify?Equivalent to \b-b\b.]" "[+nounset?Equivalent to \b-u\b.]" -#if SHOPT_BASH - "[+onecmd?Equivalent to \b-t\b. Available in bash compatibility " - "mode only.]" - "[+physical?Equivalent to \b-P\b. Available in bash " - "compatibility mode only.]" - "[+posix?Turn on POSIX compatibility. Available in bash " - "compatibility mode only. Bash in POSIX mode is not the " - "same as ksh.]" -#endif "[+pipefail?A pipeline will not complete until all components " "of the pipeline have completed, and the exit status " "of the pipeline will be the value of the last " "command to exit with non-zero exit status, or will " "be zero if all commands return zero exit status.]" + "[+posix?Enable POSIX standard compatibility mode.]" "[+privileged?Equivalent to \b-p\b.]" "[+rc?Do not run the \b.kshrc\b file for interactive shells.]" "[+showme?Simple commands preceded by a \b;\b will be traced " @@ -289,9 +270,6 @@ const char sh_set[] = "[x?Execution trace. The shell will display each command after all " "expansion and before execution preceded by the expanded value " "of the \bPS4\b parameter.]" -#if SHOPT_BASH - "\fbash1\f" -#endif #if SHOPT_BRACEPAT "[B?Enable {...} group expansion. On by default.]" #endif @@ -1569,9 +1547,6 @@ USAGE_LICENSE "[I:regress]:[intercept?Enable the regression test \aintercept\a. Must be " "the first command line option(s).]" #endif -#if SHOPT_BASH - "\fbash2\f" -#endif "\fabc\f" "?" "[T?Enable implementation specific test code defined by mask.]#[mask]" diff --git a/src/cmd/ksh93/data/lexstates.c b/src/cmd/ksh93/data/lexstates.c index 90938c13a..b06d8ca43 100644 --- a/src/cmd/ksh93/data/lexstates.c +++ b/src/cmd/ksh93/data/lexstates.c @@ -402,7 +402,6 @@ const char e_lexobsolete3[] = "line %d: '=' obsolete, use '=='"; const char e_lexobsolete4[] = "line %d: %s within [[...]] obsolete, use ((...))"; const char e_lexobsolete5[] = "line %d: set %s obsolete"; const char e_lexobsolete6[] = "line %d: `{' instead of `in' is obsolete"; -const char e_lexnonstandard[] = "line %d: `&>file' is nonstandard -- interpreted as `>file 2>&1' for profile input only"; const char e_lexusebrace[] = "line %d: use braces to avoid ambiguities with $id[...]"; const char e_lexusequote[] = "line %d: %c within ${} should be quoted"; const char e_lexescape[] = "line %d: escape %c to avoid ambiguities"; diff --git a/src/cmd/ksh93/data/msg.c b/src/cmd/ksh93/data/msg.c index d0721a9ba..c3269c6c0 100644 --- a/src/cmd/ksh93/data/msg.c +++ b/src/cmd/ksh93/data/msg.c @@ -187,15 +187,6 @@ const char e_suidprofile[] = "/etc/suid_profile"; #if SHOPT_SYSRC const char e_sysrc[] = "/etc/ksh.kshrc"; #endif -#if SHOPT_BASH -#if SHOPT_SYSRC -const char e_bash_sysrc[] = "/etc/bash.bashrc"; -#endif -const char e_bash_rc[] = "$HOME/.bashrc"; -const char e_bash_login[] = "$HOME/.bash_login"; -const char e_bash_logout[] = "$HOME/.bash_logout"; -const char e_bash_profile[] = "$HOME/.bash_profile"; -#endif const char e_crondir[] = "/usr/spool/cron/atjobs"; const char e_prohibited[] = "login setuid/setgid shells prohibited"; #ifdef BUILD_DTKSH diff --git a/src/cmd/ksh93/data/options.c b/src/cmd/ksh93/data/options.c index 73617f19d..785a8e81f 100644 --- a/src/cmd/ksh93/data/options.c +++ b/src/cmd/ksh93/data/options.c @@ -23,14 +23,6 @@ #include "name.h" #include "shtable.h" -#if SHOPT_BASH -# define bashopt(a,b) a, b|SH_BASHOPT, -# define bashextra(a,b) a, b|SH_BASHEXTRA, -#else -# define bashopt(a,b) -# define bashextra(a,b) -#endif - /* * This is the list of invocation and set options * This list must be in in ascii sorted order @@ -39,83 +31,42 @@ const Shtable_t shtab_options[] = { "allexport", SH_ALLEXPORT, -#if SHOPT_BASH - "bash", (SH_BASH|SH_COMMANDLINE), -#endif "bgnice", SH_BGNICE, "braceexpand", SH_BRACEEXPAND, - bashopt("cdable_vars", SH_CDABLE_VARS) - bashopt("cdspell", SH_CDSPELL) - bashopt("checkhash", SH_CHECKHASH) - bashopt("checkwinsize", SH_CHECKWINSIZE) "noclobber", SH_NOCLOBBER, - bashopt("dotglob", SH_DOTGLOB) "emacs", SH_EMACS, "errexit", SH_ERREXIT, "noexec", SH_NOEXEC, - bashopt("execfail", SH_EXECFAIL) - bashopt("expand_aliases", SH_EXPAND_ALIASES) - bashopt("extglob", SH_EXTGLOB) "noglob", SH_NOGLOB, "globstar", SH_GLOBSTARS, "gmacs", SH_GMACS, - bashextra("hashall", SH_TRACKALL) - bashopt("histappend", SH_HISTAPPEND) #if SHOPT_HISTEXPAND "histexpand", SH_HISTEXPAND, -#else - bashextra("histexpand", SH_HISTEXPAND) #endif - bashextra("history", SH_HISTORY2) - bashopt("histreedit", SH_HISTREEDIT) - bashopt("histverify", SH_HISTVERIFY) - bashopt("hostcomplete", SH_HOSTCOMPLETE) - bashopt("huponexit", SH_HUPONEXIT) "ignoreeof", SH_IGNOREEOF, "interactive", SH_INTERACTIVE|SH_COMMANDLINE, - bashextra("interactive_comments", SH_INTERACTIVE_COMM) "keyword", SH_KEYWORD, "letoctal", SH_LETOCTAL, - bashopt("lithist", SH_LITHIST) "nolog", SH_NOLOG, "login_shell", SH_LOGIN_SHELL|SH_COMMANDLINE, - bashopt("mailwarn", SH_MAILWARN) "markdirs", SH_MARKDIRS, "monitor", SH_MONITOR, "multiline", SH_MULTILINE, - bashopt("no_empty_cmd_completion", SH_NOEMPTYCMDCOMPL) - bashopt("nocaseglob", SH_NOCASEGLOB) "notify", SH_NOTIFY, - bashopt("nullglob", SH_NULLGLOB) - bashextra("onecmd", SH_TFLAG) "pipefail", SH_PIPEFAIL, - bashextra("physical", SH_PHYSICAL) - bashextra("posix", SH_POSIX) + "posix", SH_POSIX, "privileged", SH_PRIVILEGED, -#if SHOPT_BASH - "profile", SH_LOGIN_SHELL|SH_COMMANDLINE, -# if SHOPT_PFSH - "pfsh", SH_PFSH|SH_COMMANDLINE, -# endif -#else -# if SHOPT_PFSH +#if SHOPT_PFSH "profile", SH_PFSH|SH_COMMANDLINE, -# endif #endif - bashopt("progcomp", SH_PROGCOMP) - bashopt("promptvars", SH_PROMPTVARS) "rc", SH_RC|SH_COMMANDLINE, "restricted", SH_RESTRICTED, - bashopt("restricted_shell", SH_RESTRICTED2|SH_COMMANDLINE) - bashopt("shift_verbose", SH_SHIFT_VERBOSE) "showme", SH_SHOWME, - bashopt("sourcepath", SH_SOURCEPATH) "trackall", SH_TRACKALL, "nounset", SH_NOUNSET, "verbose", SH_VERBOSE, "vi", SH_VI, "viraw", SH_VIRAW, - bashopt("xpg_echo", SH_XPG_ECHO) "xtrace", SH_XTRACE, "", 0 }; diff --git a/src/cmd/ksh93/include/builtins.h b/src/cmd/ksh93/include/builtins.h index 76d3a79f9..7962efd81 100644 --- a/src/cmd/ksh93/include/builtins.h +++ b/src/cmd/ksh93/include/builtins.h @@ -58,11 +58,6 @@ #define SYSDOT (shgd->bltin_cmds+20) /* . */ #define SYSSOURCE (shgd->bltin_cmds+21) /* source */ #define SYSRETURN (shgd->bltin_cmds+22) /* return */ -#if SHOPT_BASH -# define SYSLOCAL (shgd->bltin_cmds+23) /* local */ -#else -# define SYSLOCAL 0 -#endif /* entry point for shell special builtins */ diff --git a/src/cmd/ksh93/include/defs.h b/src/cmd/ksh93/include/defs.h index e56a53739..06a021e75 100644 --- a/src/cmd/ksh93/include/defs.h +++ b/src/cmd/ksh93/include/defs.h @@ -311,7 +311,6 @@ struct shared #define SH_COMPLETE 19 /* set for command completion */ #define SH_INTESTCMD 20 /* set while test/[ command is being run */ -#define SH_BASH 41 #define SH_BRACEEXPAND 42 #define SH_POSIX 46 #define SH_MULTILINE 47 @@ -319,9 +318,7 @@ struct shared #define SH_NOPROFILE 78 #define SH_NOUSRPROFILE 79 #define SH_LOGIN_SHELL 67 -#define SH_COMMANDLINE 0x100 -#define SH_BASHEXTRA 0x200 -#define SH_BASHOPT 0x400 +#define SH_COMMANDLINE 0x100 /* flag for invocation-only options ('set -o' cannot change them) */ #define SH_ID "ksh" /* ksh id */ #define SH_STD "sh" /* standard sh id */ @@ -330,44 +327,11 @@ struct shared #define SH_TYPE_SH 001 #define SH_TYPE_KSH 002 -#define SH_TYPE_BASH 004 +#define SH_TYPE_POSIX 004 #define SH_TYPE_LOGIN 010 #define SH_TYPE_PROFILE 020 #define SH_TYPE_RESTRICTED 040 -#if SHOPT_BASH -# ifndef SHOPT_HISTEXPAND -# define SHOPT_HISTEXPAND 1 -# endif -/* - * define for all the bash options - */ -# define SH_CDABLE_VARS 51 -# define SH_CDSPELL 52 -# define SH_CHECKHASH 53 -# define SH_CHECKWINSIZE 54 -# define SH_CMDHIST 55 -# define SH_DOTGLOB 56 -# define SH_EXECFAIL 57 -# define SH_EXPAND_ALIASES 58 -# define SH_EXTGLOB 59 -# define SH_HOSTCOMPLETE 63 -# define SH_HUPONEXIT 64 -# define SH_INTERACTIVE_COMM 65 -# define SH_LITHIST 66 -# define SH_MAILWARN 68 -# define SH_NOEMPTYCMDCOMPL 69 -# define SH_NOCASEGLOB 70 -# define SH_NULLGLOB 71 -# define SH_PHYSICAL 45 -# define SH_PROGCOMP 72 -# define SH_PROMPTVARS 73 -# define SH_RESTRICTED2 74 -# define SH_SHIFT_VERBOSE 75 -# define SH_SOURCEPATH 76 -# define SH_XPG_ECHO 77 -#endif - #if SHOPT_HISTEXPAND # define SH_HISTAPPEND 60 # define SH_HISTEXPAND 43 @@ -483,7 +447,6 @@ extern const char e_dict[]; #define PRINT_VERBOSE 0x01 /* option on|off list */ #define PRINT_ALL 0x02 /* list unset options too */ #define PRINT_NO_HEADER 0x04 /* omit listing header */ -#define PRINT_SHOPT 0x08 /* shopt -s|-u */ #define PRINT_TABLE 0x10 /* table of all options */ #ifdef SHOPT_STATS diff --git a/src/cmd/ksh93/include/io.h b/src/cmd/ksh93/include/io.h index f82c5ca10..ee7d0cb92 100644 --- a/src/cmd/ksh93/include/io.h +++ b/src/cmd/ksh93/include/io.h @@ -114,15 +114,6 @@ extern const char e_sysprofile[]; #if SHOPT_SYSRC extern const char e_sysrc[]; #endif -#if SHOPT_BASH -#if SHOPT_SYSRC -extern const char e_bash_sysrc[]; -#endif -extern const char e_bash_rc[]; -extern const char e_bash_login[]; -extern const char e_bash_logout[]; -extern const char e_bash_profile[]; -#endif extern const char e_stdprompt[]; extern const char e_supprompt[]; extern const char e_ambiguous[]; diff --git a/src/cmd/ksh93/include/shlex.h b/src/cmd/ksh93/include/shlex.h index bc38ccb3d..1574796f2 100644 --- a/src/cmd/ksh93/include/shlex.h +++ b/src/cmd/ksh93/include/shlex.h @@ -41,7 +41,6 @@ typedef struct _shlex_ int lastline; /* last line number */ int lasttok; /* previous token number */ int digits; /* numerical value with word token */ - int nonstandard; /* nonstandard construct in profile */ char aliasok; /* on when alias is legal */ char assignok; /* on when name=value is legal */ char inexec; /* on when processing exec */ diff --git a/src/cmd/ksh93/include/version.h b/src/cmd/ksh93/include/version.h index 9d19bb453..8d37c84b0 100644 --- a/src/cmd/ksh93/include/version.h +++ b/src/cmd/ksh93/include/version.h @@ -17,4 +17,4 @@ * David Korn * * * ***********************************************************************/ -#define SH_RELEASE "93u+m 2020-08-19" +#define SH_RELEASE "93u+m 2020-09-01" diff --git a/src/cmd/ksh93/sh.1 b/src/cmd/ksh93/sh.1 index a65b7dc4c..e8648b3fa 100644 --- a/src/cmd/ksh93/sh.1 +++ b/src/cmd/ksh93/sh.1 @@ -3409,7 +3409,7 @@ successfully rename it to otherwise, delete the temporary file. .BI >; word cannot be used with the -.IR exec (2). +.IR exec built-in. .TP .BI >> word @@ -3433,7 +3433,7 @@ except that if the command completes successfully, is truncated to the offset at command completion. .BI <>; word cannot be used with the -.IR exec (2). +.IR exec built-in. .TP \f3<<\fP\*(OK\f3\-\fP\*(CK\f2word\fP @@ -3492,20 +3492,26 @@ The standard input is duplicated from file descriptor .I digit (see .IR dup (2)). -Similarly for the standard output using -\f3>&\^\f2digit\fR. +.TP +.BI >& digit +The standard output is duplicated from file descriptor +.IR digit . .TP .BI <& digit \- The file descriptor given by .I digit is moved to standard input. -Similarly for the standard output using -\f3>&\^\f2digit\f3\-\fR. +.TP +.BI >& digit \- +The file descriptor given by +.I digit +is moved to standard output. .TP .B <&\- The standard input is closed. -Similarly for the standard output using -.BR >&\- . +.TP +.B >&\- +The standard output is closed. .TP .B <&p The input from the co-process is moved to standard input. @@ -3593,6 +3599,11 @@ for reading and store the file descriptor number in variable .BR n . .PP +A special shorthand redirection operator \fB&>\fR\fIword\fR is available; it +is equivalent to \fB>\fR\fIword\fR\fB 2>&1\fR. It cannot be preceded by any +digit or variable name. This shorthand is disabled if the \fIposix\fR shell +option is active. +.PP The order in which redirections are specified is significant. The shell evaluates each redirection in terms of the .RI ( "file descriptor" ", " file ) @@ -7020,6 +7031,11 @@ of the pipeline have completed, and the return value will be the value of the last non-zero command to fail or zero if no command has failed. .TP 8 +.B posix +Enable POSIX standard compatibility mode. This option +is on by default if ksh is invoked as \fBsh\fR. It +disables the \fB&>\fR redirection shorthand. +.TP 8 .B privileged Same as .BR \-p . diff --git a/src/cmd/ksh93/sh/args.c b/src/cmd/ksh93/sh/args.c index 4c5c6b060..b4fe735a8 100644 --- a/src/cmd/ksh93/sh/args.c +++ b/src/cmd/ksh93/sh/args.c @@ -42,11 +42,6 @@ #else # define PFSHOPT #endif -#if SHOPT_BASH -# define BASHOPT "\374" -#else -# define BASHOPT -#endif #if SHOPT_HISTEXPAND # define HFLAG "H" #else @@ -59,15 +54,13 @@ static char *null; /* The following order is determined by sh_optset */ -static const char optksh[] = PFSHOPT BASHOPT "DircabefhkmnpstuvxBCGEl" HFLAG; +static const char optksh[] = PFSHOPT "\374" "DircabefhkmnpstuvxBCGEl" HFLAG; static const int flagval[] = { #if SHOPT_PFSH SH_PFSH, #endif -#if SHOPT_BASH SH_POSIX, -#endif SH_DICTIONARY, SH_INTERACTIVE, SH_RESTRICTED, SH_CFLAG, SH_ALLEXPORT, SH_NOTIFY, SH_ERREXIT, SH_NOGLOB, SH_TRACKALL, SH_KEYWORD, SH_MONITOR, SH_NOEXEC, SH_PRIVILEGED, SH_SFLAG, SH_TFLAG, @@ -108,22 +101,6 @@ void *sh_argopen(Shell_t *shp) static int infof(Opt_t* op, Sfio_t* sp, const char* s, Optdisc_t* dp) { -#if SHOPT_BASH - extern const char sh_bash1[], sh_bash2[]; - if(strcmp(s,"bash1")==0) - { - if(sh_isoption(SH_BASH)) - sfputr(sp,sh_bash1,-1); - } - else if(strcmp(s,"bash2")==0) - { - if(sh_isoption(SH_BASH)) - sfputr(sp,sh_bash2,-1); - } - else if(*s==':' && sh_isoption(SH_BASH)) - sfputr(sp,s,-1); - else -#endif if(*s!=':') sfputr(sp,sh_set,-1); return(1); @@ -168,31 +145,17 @@ int sh_argopts(int argc,register char *argv[], void *context) if(f) nv_unset(np); continue; -#if SHOPT_BASH - case 'O': /* shopt options, only in bash mode */ - if(!sh_isoption(SH_BASH)) - errormsg(SH_DICT,ERROR_exit(1), e_option, opt_info.name); -#endif case 'o': /* set options */ byname: if(!opt_info.arg||!*opt_info.arg||*opt_info.arg=='-') { action = PRINT; - /* print style: -O => shopt options - * bash => print unset options also, no heading - */ verbose = (f?PRINT_VERBOSE:PRINT_NO_HEADER)| - (n=='O'?PRINT_SHOPT:0)| - (sh_isoption(SH_BASH)?PRINT_ALL|PRINT_NO_HEADER:0)| ((opt_info.arg&&(!*opt_info.arg||*opt_info.arg=='-'))?(PRINT_TABLE|PRINT_NO_HEADER):0); continue; } o = sh_lookopt(opt_info.arg,&f); - if(o<=0 - || (!sh_isoption(SH_BASH) && (o&SH_BASHEXTRA)) - || ((!sh_isoption(SH_BASH) || n=='o') && (o&SH_BASHOPT)) - - || (setflag && (o&SH_COMMANDLINE))) + if(o<=0 || (setflag && (o&SH_COMMANDLINE))) { errormsg(SH_DICT,2, e_option, opt_info.arg); error_info.errors++; @@ -201,33 +164,6 @@ int sh_argopts(int argc,register char *argv[], void *context) if(sh_isoption(SH_RESTRICTED) && !f && o==SH_RESTRICTED) errormsg(SH_DICT,ERROR_exit(1), e_restricted, opt_info.arg); break; -#if SHOPT_BASH - case -1: /* --rcfile */ - ap->sh->gd->rcfile = opt_info.arg; - continue; - case -2: /* --noediting */ - if (!f) - { - off_option(&newflags,SH_VI); - off_option(&newflags,SH_EMACS); - off_option(&newflags,SH_GMACS); - } - continue; - case -3: /* --profile */ - n = 'l'; - goto skip; - case -4: /* --posix */ - /* mask lower 8 bits to find char in optksh string */ - n&=0xff; - goto skip; - case -5: /* --version */ - sfputr(sfstdout, "ksh bash emulation, version ",-1); - np = nv_open("BASH_VERSION",ap->sh->var_tree,0); - sfputr(sfstdout, nv_getval(np),-1); - np = nv_open("MACHTYPE",ap->sh->var_tree,0); - sfprintf(sfstdout, " (%s)\n", nv_getval(np)); - sh_exit(0); -#endif case -6: /* --default */ { register const Shtable_t *tp; @@ -408,35 +344,6 @@ void sh_applyopts(Shell_t* shp,Shopt_t newflags) (shp->gd->userid==shp->gd->euserid && shp->gd->groupid==shp->gd->egroupid)) off_option(&newflags,SH_PRIVILEGED); } -#if SHOPT_BASH - on_option(&newflags,SH_CMDHIST); - on_option(&newflags,SH_CHECKHASH); - on_option(&newflags,SH_EXECFAIL); - on_option(&newflags,SH_EXPAND_ALIASES); - on_option(&newflags,SH_HISTAPPEND); - on_option(&newflags,SH_INTERACTIVE_COMM); - on_option(&newflags,SH_LITHIST); - on_option(&newflags,SH_NOEMPTYCMDCOMPL); - - if(!is_option(&newflags,SH_XPG_ECHO) && sh_isoption(SH_XPG_ECHO)) - astconf("UNIVERSE", 0, "ucb"); - if(is_option(&newflags,SH_XPG_ECHO) && !sh_isoption(SH_XPG_ECHO)) - astconf("UNIVERSE", 0, "att"); - if(!is_option(&newflags,SH_PHYSICAL) && sh_isoption(SH_PHYSICAL)) - astconf("PATH_RESOLVE", 0, "metaphysical"); - if(is_option(&newflags,SH_PHYSICAL) && !sh_isoption(SH_PHYSICAL)) - astconf("PATH_RESOLVE", 0, "physical"); - if(is_option(&newflags,SH_HISTORY2) && !sh_isoption(SH_HISTORY2)) - { - sh_onstate(SH_HISTORY); - sh_onoption(SH_HISTORY); - } - if(!is_option(&newflags,SH_HISTORY2) && sh_isoption(SH_HISTORY2)) - { - sh_offstate(SH_HISTORY); - sh_offoption(SH_HISTORY); - } -#endif shp->options = newflags; } @@ -647,23 +554,11 @@ void sh_printopts(Shopt_t oflags,register int mode, Shopt_t *mask) on_option(&oflags,SH_VIRAW); #endif if(!(mode&(PRINT_ALL|PRINT_VERBOSE))) /* only print set options */ - { - if(mode&PRINT_SHOPT) - sfwrite(sfstdout,"shopt -s",3); - else - sfwrite(sfstdout,"set --default",13); - } + sfwrite(sfstdout,"set --default",13); for(tp=shtab_options; value=tp->sh_number; tp++) { if(mask && !is_option(mask,value&0xff)) continue; - if(sh_isoption(SH_BASH)) - { - if (!(mode&PRINT_SHOPT) != !(value&SH_BASHOPT)) - continue; - } - else if (value&(SH_BASHEXTRA|SH_BASHOPT)) - continue; on = !!is_option(&oflags,value); name = tp->sh_name; if(name[0] == 'n' && name[1] == 'o' && name[2] != 't') @@ -678,18 +573,9 @@ void sh_printopts(Shopt_t oflags,register int mode, Shopt_t *mask) sfputr(sfstdout,on ? sh_translate(e_on) : sh_translate(e_off),'\n'); } else if(mode&PRINT_ALL) /* print unset options also */ - { - if(mode&PRINT_SHOPT) - sfprintf(sfstdout, "shopt -%c %s\n", - on?'s':'u', - name); - else - sfprintf(sfstdout, "set %co %s\n", - on?'-':'+', - name); - } + sfprintf(sfstdout, "set %co %s\n", on?'-':'+', name); else if(!(value&SH_COMMANDLINE) && is_option(&oflags,value&0xff)) - sfprintf(sfstdout," %s%s%s",(mode&PRINT_SHOPT)?"":"--",on?"":"no",name); + sfprintf(sfstdout, " %s%s%s","--", on?"":"no", name); } if(!(mode&(PRINT_VERBOSE|PRINT_ALL))) sfputc(sfstdout,'\n'); diff --git a/src/cmd/ksh93/sh/bash.c b/src/cmd/ksh93/sh/bash.c deleted file mode 100644 index 8e960a765..000000000 --- a/src/cmd/ksh93/sh/bash.c +++ /dev/null @@ -1,423 +0,0 @@ -/*********************************************************************** -* * -* This software is part of the ast package * -* Copyright (c) 1982-2011 AT&T Intellectual Property * -* and is licensed under the * -* Eclipse Public License, Version 1.0 * -* by AT&T Intellectual Property * -* * -* A copy of the License is available at * -* http://www.eclipse.org/org/documents/epl-v10.html * -* (with md5 checksum b35adb5213ca9657e911e9befb180842) * -* * -* Information and Software Systems Research * -* AT&T Research * -* Florham Park NJ * -* * -* David Korn * -* * -***********************************************************************/ -/* - * bash specific extensions - * originally provided by Karsten Fleischer - */ - -#include "defs.h" -#include "path.h" -#include "io.h" -#include "builtins.h" -#include "name.h" - -#ifndef BASH_MAJOR -# define BASH_MAJOR "1" -# define BASH_MINOR "0" -# define BASH_PATCH "0" -# define BASH_BUILD "0" -# define BASH_RELEASE "experimental" -#endif -#define BASH_VERSION BASH_MAJOR "." BASH_MINOR "." BASH_PATCH "(" BASH_BUILD ")-" BASH_RELEASE - - -extern const char bash_pre_rc[]; - -static char *login_files[4]; - -const char sh_bash1[] = - "[B?Enable brace group expansion. This option is only available in bash " - "compatibility mode. In ksh mode, brace group expansion is always on.]" - "[P?Do not follow symbolic links, use physical directory structure " - "instead. Only available in bash compatibility mode.]"; -const char sh_bash2[] = -"[O]:?[shopt_option?\ashopt_option\a is one of the shell options accepted by " - "the \bshopt\b builtin. If \ashopt_option\a is present, \b-O\b sets " - "the value of that option; \b+O\b unsets it. If \ashopt_option\a is " - "not supplied, the names and values of the shell options accepted by " - "\bshopt\b are printed on the standard output. If the invocation " - "option is \b+O\b, the output is displayed in a format that may be " - "reused as input. Only available if invoked as \bbash\b.]" -"[01:init-file|rcfile]:[file?Execute commands from \afile\a instead of the " - "standard personal initialization file ~/.bashrc if the shell is " - "interactive. Only available if invoked as \bbash\b.]" -"[02:editing?For option compatibility with \bbash\b only. Ignored.]" -"[03:profile?Read either the system-wide startup file or any of the " - "personal initialization files. On by default for interactive " - "shells. Only available if invoked as \bbash\b.]" -"[04:posix?If invoked as \bbash\b, turn on POSIX compatibility. \bBash\b in " - "POSIX mode is not the same as \bksh\b.]" -"[05:version?Print version number and exit.]"; - -const char sh_optshopt[] = -"+[-1c?\n@(#)$Id: shopt (AT&T Research) 2003-02-13 $\n]" -"[-author?Karsten Fleischer ]" -USAGE_LICENSE -"[+NAME?shopt - set/unset variables controlling optional shell behavior]" -"[+DESCRIPTION?\bshopt\b sets or unsets variables controlling optional shell " - "behavior. With no options, or with the \b-p\b option, a list of all " - "settable options is displayed, with an indication of whether or not " - "each is set.]" -"[p?Causes output to be displayed in a form that may be reused as input.]" -"[s?Set each \aoptname\a.]" -"[u?Unset each \aoptname\a.]" -"[q?Suppress output (quiet mode). The return status indicates whether the " - "\aoptname\a is set or unset. If multiple \aoptname\a arguments are " - "given with \b-q\b, the return status is zero if all \aoptname\as are " - "enabled; non-zero otherwise.]" -"[o?Restricts the values of \aoptname\a to be those defined for the \b-o\b " - "option to the set builtin.]" -"[+?If either \b-s\b or \b-u\b is used with no \aoptname\a arguments, the " - "display is limited to those options which are set or unset.]" -"[+?\bshopt\b supports all bash options. Some settings do not have any effect " - "or are are always on and cannot be changed.]" -"[+?The value of \aoptname\a must be one of the following:]{" - "[+cdable_vars?If set, arguments to the \bcd\b command are " - "assumed to be names of variables whose values are to " - "be used if the usual \bcd\b proceeding fails.]" - "[+cdspell?Currently ignored.]" - "[+checkhash?Always on.]" - "[+checkwinsize?Currently ignored.]" - "[+cmdhist?Always on.]" - "[+dotglob?If set, include filenames beginning with a \b.\b " - "in the results of pathname expansion.]" - "[+execfail?Always on.]" - "[+expand_aliases?Always on.]" - "[+extglob?Enable extended pattern matching features.]" - "[+histappend?Always on.]" - "[+histreedit?If set and an edit mode is selected, the user " - "is given the opportunity to re-edit a failed history " - "substitution.]" - "[+histverify?If set and an edit mode is selected, the result " - "of a history substitution will not be executed " - "immediately but be placed in the edit buffer for " - "further modifications.]" - "[+hostcomplete?Currently ignored.]" - "[+huponexit?Currently ignored.]" - "[+interactive_comments?Always on.]" - "[+lithist?Always on.]" - "[+login_shell?This option is set if the shell is started as " - "a login shell. The value cannot be changed.]" - "[+mailwarn?Currently ignored.]" - "[+no_empty_cmd_completion?Always on.]" - "[+nocaseglob?Match filenames in a case-insensitive fashion " - "when performing filename expansion.]" - "[+nullglob?Allows filename patterns which match no files to " - "expand to a null string, rather than themselves.]" - "[+progcomp?Currently ignored.]" - "[+promptvars?Currently ignored.]" - "[+restricted_shell?This option is set if the shell is started " - "as a restricted shell. The value cannot be changed. " - "It is not reset during execution of startup files, " - "allowing the startup files to determine whether the " - "shell is restricted.]" - "[+shift_verbose?Currently ignored.]" - "[+sourcepath?If set, the \b.\b builtin uses the value of PATH " - "to find the directory containing the file supplied " - "as an argument.]" - "[+xpg_echo?If set, the \becho\b and \bprint\b builtins " - "expand backslash-escape sequences.]" -"}" -"\n" -"\n[optname ...]\n" -"\n" -"[+EXIT STATUS?]{" - "[+?The return status when listing options is zero if all \aoptnames\a " - "are enabled, non-zero otherwise. When setting or unsetting options, " - "the return status is zero unless an \aoptname\a is not a valid shell " - "option.]" -"}" - -"[+SEE ALSO?\bset\b(1)]" -; - -/* GLOBIGNORE discipline. Turn on SH_DOTGLOB on set, turn off on unset. */ - -static void put_globignore(register Namval_t* np, const char *val, int flags, Namfun_t *fp) -{ - if(val) - sh_onoption(SH_DOTGLOB); - else - sh_offoption(SH_DOTGLOB); - - nv_putv(np,val,flags,fp); -} - -const Namdisc_t SH_GLOBIGNORE_disc = { sizeof(Namfun_t), put_globignore }; - -/* FUNCNAME discipline */ - -struct funcname -{ - Namfun_t hdr; -}; - -static void put_funcname(register Namval_t* np,const char *val,int flags,Namfun_t *fp) -{ - /* bash silently returns with an error when FUNCNAME is set, - unsetting FUNCNAME is allowed */ - if(val && !(flags&NV_RDONLY)) - error_info.exit(1); - - nv_putv(np,val,flags,fp); -} - -const Namdisc_t SH_FUNCNAME_disc = { sizeof(struct funcname), put_funcname }; - -#define SET_SET 1 -#define SET_UNSET 2 -#define SET_NOARGS 4 - -/* shopt builtin */ - -int b_shopt(int argc,register char *argv[],void *extra) -{ - Shell_t *shp = (Shell_t*)extra; - int n, f, ret=0; - Shopt_t newflags=shp->options, opt; - int verbose=PRINT_SHOPT|PRINT_ALL|PRINT_NO_HEADER|PRINT_VERBOSE; - int setflag=0, quietflag=0, oflag=0; - memset(&opt,0,sizeof(opt)); -#if SHOPT_RAWONLY - on_option(&newflags,SH_VIRAW); -#endif - while((n = optget(argv,sh_optshopt))) - { - switch(n) - { - case 'p': - verbose&=~PRINT_VERBOSE; - break; - case 's': - case 'u': - setflag|=n=='s'?SET_SET:SET_UNSET; - if(setflag==(SET_SET|SET_UNSET)) - { - errormsg(SH_DICT,ERROR_ERROR,"cannot set and unset options simultaneously"); - error_info.errors++; - } - break; - case 'q': - quietflag=1; - break; - case 'o': - oflag=1; - verbose&=~PRINT_SHOPT; - break; - case ':': - errormsg(SH_DICT,2, "%s", opt_info.arg); - continue; - case '?': - errormsg(SH_DICT,ERROR_usage(0), "%s", opt_info.arg); - return(-1); - } - } - if(error_info.errors) - errormsg(SH_DICT,ERROR_usage(2),"%s",optusage(NIL(char*))); - argc -= opt_info.index; - if(argc==0) - { - /* no args, -s => mask=current options, -u mask=~(current options) - else mask=all bits */ - if(setflag&SET_SET) - opt=newflags; - else if(setflag&SET_UNSET) - for(n=0;n<4;n++) - opt.v[n]=~newflags.v[n]; - else - memset(&opt,0xff,sizeof(opt)); - setflag=SET_NOARGS; - } - while(argc>0) - { - f=1; - n=sh_lookopt(argv[opt_info.index],&f); - if(n<=0||(setflag - && (is_option(&opt,SH_INTERACTIVE) - || is_option(&opt,SH_RESTRICTED) - || is_option(&opt,SH_RESTRICTED2) - || is_option(&opt,SH_BASH) - || is_option(&opt,SH_LOGIN_SHELL))) - ||(oflag&&(n&SH_BASHOPT))) - { - errormsg(SH_DICT,ERROR_ERROR, e_option, argv[opt_info.index]); - error_info.errors++; - ret=1; - } - else if(f) - on_option(&opt,n&0xff); - else - off_option(&opt,n&0xff); - opt_info.index++; - argc--; - } - if(setflag&(SET_SET|SET_UNSET)) - { - if(setflag&SET_SET) - { - if(sh_isoption(SH_INTERACTIVE)) - off_option(&opt,SH_NOEXEC); - if(is_option(&opt,SH_VI)||is_option(&opt,SH_EMACS)||is_option(&opt,SH_GMACS)) - { - off_option(&newflags,SH_VI); - off_option(&newflags,SH_EMACS); - off_option(&newflags,SH_GMACS); - } - for(n=0;n<4;n++) - newflags.v[n] |= opt.v[n]; - } - else if(setflag&SET_UNSET) - for(n=0;n<4;n++) - newflags.v[n] &= ~opt.v[n]; - sh_applyopts(shp,newflags); - shp->options = newflags; - if(is_option(&newflags,SH_XTRACE)) - sh_trace(shp,argv,1); - } - else if(!(setflag&SET_NOARGS)) /* no -s,-u but args, ret=0 if opt&mask==mask */ - { - for(n=0;n<4;n++) - ret+=((newflags.v[n]&opt.v[n])!=opt.v[n]); - } - if(!quietflag&&!(setflag&(SET_SET|SET_UNSET))) - sh_printopts(newflags,verbose,&opt); - return(ret); -} - -/* mode = 0: init, called two times - before parsing shell args with SH_PREINIT state turned on - second time after sh_init() is through and with SH_PREINIT state turned off - mode > 1: re-init - mode < 0: shutdown -*/ - -void bash_init(Shell_t *shp,int mode) -{ - Sfio_t *iop; - Namval_t *np; - int n=0,xtrace,verbose; - if(mode>0) - goto reinit; - if(mode < 0) - { - /* termination code */ - if(sh_isoption(SH_LOGIN_SHELL) && !sh_isoption(SH_POSIX)) - sh_source(shp, NiL, sh_mactry(shp,(char*)e_bash_logout)); - return; - } - - if(sh_isstate(SH_PREINIT)) - { /* pre-init stage */ - if(sh_isoption(SH_RESTRICTED)) - sh_onoption(SH_RESTRICTED2); - sh_onoption(SH_HISTORY2); - sh_onoption(SH_INTERACTIVE_COMM); - sh_onoption(SH_SOURCEPATH); - sh_onoption(SH_HISTAPPEND); - sh_onoption(SH_CMDHIST); - sh_onoption(SH_LITHIST); - sh_onoption(SH_NOEMPTYCMDCOMPL); - if(shp->login_sh==2) - sh_onoption(SH_LOGIN_SHELL); - if(strcmp(astconf("CONFORMANCE",0,0),"standard")==0) - sh_onoption(SH_POSIX); - if(strcmp(astconf("UNIVERSE",0,0),"att")==0) - sh_onoption(SH_XPG_ECHO); - else - sh_offoption(SH_XPG_ECHO); - if(strcmp(astconf("PATH_RESOLVE",0,0),"physical")==0) - sh_onoption(SH_PHYSICAL); - else - sh_offoption(SH_PHYSICAL); - - /* add builtins */ - sh_addbuiltin("shopt", b_shopt, &sh); - - /* set up some variables needed for --version - * needs to go here because --version option is parsed before the init script. - */ - if(np=nv_open("HOSTTYPE",shp->var_tree,0)) - nv_putval(np, BASH_HOSTTYPE, NV_NOFREE); - if(np=nv_open("MACHTYPE",shp->var_tree,0)) - nv_putval(np, BASH_MACHTYPE, NV_NOFREE); - if(np=nv_open("BASH_VERSION",shp->var_tree,0)) - nv_putval(np, BASH_VERSION, NV_NOFREE); - if(np=nv_open("BASH_VERSINFO",shp->var_tree,0)) - { - char *argv[7]; - argv[0] = BASH_MAJOR; - argv[1] = BASH_MINOR; - argv[2] = BASH_PATCH; - argv[3] = BASH_BUILD; - argv[4] = BASH_RELEASE; - argv[5] = BASH_MACHTYPE; - argv[6] = 0; - nv_setvec(np, 0, 6, argv); - nv_onattr(np,NV_RDONLY); - } - return; - } - - /* rest of init stage */ - - /* restrict BASH_ENV */ - if(np=nv_open("BASH_ENV",shp->var_tree,0)) - { - const Namdisc_t *dp = nv_discfun(NV_DCRESTRICT); - Namfun_t *fp = calloc(dp->dsize,1); - fp->disc = dp; - nv_disc(np, fp, 0); - } - - /* open GLOBIGNORE node */ - if(np=nv_open("GLOBIGNORE",shp->var_tree,0)) - { - const Namdisc_t *dp = &SH_GLOBIGNORE_disc; - Namfun_t *fp = calloc(dp->dsize,1); - fp->disc = dp; - nv_disc(np, fp, 0); - } - - /* set startup files */ - n=0; - if(sh_isoption(SH_LOGIN_SHELL)) - { - if(!sh_isoption(SH_POSIX)) - { - login_files[n++] = (char*)e_bash_profile; - login_files[n++] = (char*)e_bash_login; - } - login_files[n++] = (char*)e_profile; - } - shp->login_files = login_files; -reinit: - xtrace = sh_isoption(SH_XTRACE); - sh_offoption(SH_XTRACE); - verbose = sh_isoption(SH_VERBOSE); - sh_offoption(SH_VERBOSE); - if(np = nv_open("SHELLOPTS", shp->var_tree, NV_NOADD)) - nv_offattr(np,NV_RDONLY); - iop = sfopen(NULL, bash_pre_rc, "s"); - sh_eval(iop,0); - if(xtrace) - sh_offoption(SH_XTRACE); - if(verbose) - sh_offoption(SH_VERBOSE); -} diff --git a/src/cmd/ksh93/sh/expand.c b/src/cmd/ksh93/sh/expand.c index 40c3dd19e..bfe33cf80 100644 --- a/src/cmd/ksh93/sh/expand.c +++ b/src/cmd/ksh93/sh/expand.c @@ -96,10 +96,6 @@ int path_expand(Shell_t *shp,const char *pattern, struct argnod **arghead) register struct argnod *ap; register glob_t *gp= &gdata; register int flags,extra=0; -#if SHOPT_BASH - register int off; - register char *sp, *cp, *cp2; -#endif sh_stats(STAT_GLOBS); memset(gp,0,sizeof(gdata)); flags = GLOB_GROUP|GLOB_AUGMENTED|GLOB_NOCHECK|GLOB_NOSORT|GLOB_STACK|GLOB_LIST|GLOB_DISC; @@ -107,16 +103,6 @@ int path_expand(Shell_t *shp,const char *pattern, struct argnod **arghead) flags |= GLOB_MARK; if(sh_isoption(SH_GLOBSTARS)) flags |= GLOB_STARSTAR; -#if SHOPT_BASH -#if 0 - if(sh_isoption(SH_BASH) && !sh_isoption(SH_EXTGLOB)) - flags &= ~GLOB_AUGMENTED; -#endif - if(sh_isoption(SH_NULLGLOB)) - flags &= ~GLOB_NOCHECK; - if(sh_isoption(SH_NOCASEGLOB)) - flags |= GLOB_ICASE; -#endif if(sh_isstate(SH_COMPLETE)) { #if KSHELL @@ -129,62 +115,6 @@ int path_expand(Shell_t *shp,const char *pattern, struct argnod **arghead) flags |= GLOB_COMPLETE; flags &= ~GLOB_NOCHECK; } -#if SHOPT_BASH - if(off = staktell()) - sp = stakfreeze(0); - if(sh_isoption(SH_BASH)) - { - /* - * For bash, FIGNORE is a colon separated list of suffixes to - * ignore when doing filename/command completion. - * GLOBIGNORE is similar to ksh FIGNORE, but colon separated - * instead of being an augmented shell pattern. - * Generate shell patterns out of those here. - */ - if(sh_isstate(SH_FCOMPLETE)) - cp=nv_getval(sh_scoped(shp,FIGNORENOD)); - else - { - static Namval_t *GLOBIGNORENOD; - if(!GLOBIGNORENOD) - GLOBIGNORENOD = nv_open("GLOBIGNORE",shp->var_tree,0); - cp=nv_getval(sh_scoped(shp,GLOBIGNORENOD)); - } - if(cp) - { - flags |= GLOB_AUGMENTED; - stakputs("@("); - if(!sh_isstate(SH_FCOMPLETE)) - { - stakputs(cp); - for(cp=stakptr(off); *cp; cp++) - if(*cp == ':') - *cp='|'; - } - else - { - cp2 = strtok(cp, ":"); - if(!cp2) - cp2=cp; - do - { - stakputc('*'); - stakputs(cp2); - if(cp2 = strtok(NULL, ":")) - { - *(cp2-1)=':'; - stakputc('|'); - } - } while(cp2); - } - stakputc(')'); - gp->gl_fignore = stakfreeze(1); - } - else if(!sh_isstate(SH_FCOMPLETE) && sh_isoption(SH_DOTGLOB)) - gp->gl_fignore = ""; - } - else -#endif gp->gl_fignore = nv_getval(sh_scoped(shp,FIGNORENOD)); if(suflen) gp->gl_suffix = sufstr; @@ -193,12 +123,6 @@ int path_expand(Shell_t *shp,const char *pattern, struct argnod **arghead) if(memcmp(pattern,"~(N",3)==0) flags &= ~GLOB_NOCHECK; glob(pattern, flags, 0, gp); -#if SHOPT_BASH - if(off) - stakset(sp,off); - else - stakseek(0); -#endif sh_sigcheck(shp); for(ap= (struct argnod*)gp->gl_list; ap; ap = ap->argnxt.ap) { diff --git a/src/cmd/ksh93/sh/init.c b/src/cmd/ksh93/sh/init.c index 6f7759596..a73d176c0 100644 --- a/src/cmd/ksh93/sh/init.c +++ b/src/cmd/ksh93/sh/init.c @@ -87,10 +87,6 @@ char e_version[] = "\n@(#)$Id: Version " #define ATTRS 1 "A" #endif -#if SHOPT_BASH -#define ATTRS 1 - "B" -#endif #if SHOPT_BGX #define ATTRS 1 "J" @@ -116,10 +112,6 @@ char e_version[] = "\n@(#)$Id: Version " #endif SH_RELEASE " $\0\n"; -#if SHOPT_BASH - extern void bash_init(Shell_t*,int); -#endif - #define RANDMASK 0x7fff #ifndef ARG_MAX @@ -1103,7 +1095,7 @@ int sh_type(register const char *path) } for (;;) { - if (!(t & (SH_TYPE_KSH|SH_TYPE_BASH))) + if (!(t & SH_TYPE_KSH)) { if (*s == 'k') { @@ -1111,14 +1103,6 @@ int sh_type(register const char *path) t |= SH_TYPE_KSH; continue; } -#if SHOPT_BASH - if (*s == 'b' && *(s+1) == 'a') - { - s += 2; - t |= SH_TYPE_BASH; - continue; - } -#endif } if (!(t & (SH_TYPE_PROFILE|SH_TYPE_RESTRICTED))) { @@ -1143,6 +1127,8 @@ int sh_type(register const char *path) { s++; t |= SH_TYPE_SH; + if (!(t & SH_TYPE_KSH)) + t |= SH_TYPE_POSIX; if ((t & SH_TYPE_KSH) && *s == '9' && *(s+1) == '3') s += 2; #if _WINIX @@ -1152,7 +1138,7 @@ int sh_type(register const char *path) if (!isalnum(*s)) return t; } - return t & ~(SH_TYPE_BASH|SH_TYPE_KSH|SH_TYPE_PROFILE|SH_TYPE_RESTRICTED); + return t & ~(SH_TYPE_KSH|SH_TYPE_PROFILE|SH_TYPE_RESTRICTED); } @@ -1315,6 +1301,8 @@ Shell_t *sh_init(register int argc,register char *argv[], Shinit_f userinit) type = sh_type(*argv); if(type&SH_TYPE_LOGIN) shp->login_sh = 2; + if(type&SH_TYPE_POSIX || strcmp(astconf("CONFORMANCE",0,0),"standard")==0) + sh_onoption(SH_POSIX); } env_init(shp); if(!ENVNOD->nvalue.cp) @@ -1378,17 +1366,6 @@ Shell_t *sh_init(register int argc,register char *argv[], Shinit_f userinit) /* check for profile shell */ else if(type&SH_TYPE_PROFILE) sh_onoption(SH_PFSH); -#endif -#if SHOPT_BASH - /* check for invocation as bash */ - if(type&SH_TYPE_BASH) - { - shp>userinit = userinit = bash_init; - sh_onoption(SH_BASH); - sh_onstate(SH_PREINIT); - (*userinit)(shp, 0); - sh_offstate(SH_PREINIT); - } #endif /* look for options */ /* shp->st.dolc is $# */ diff --git a/src/cmd/ksh93/sh/lex.c b/src/cmd/ksh93/sh/lex.c index dac33aa66..0988802d8 100644 --- a/src/cmd/ksh93/sh/lex.c +++ b/src/cmd/ksh93/sh/lex.c @@ -576,13 +576,9 @@ int sh_lex(Lex_t* lp) return(lp->token=c); else if(c=='&') { - if(!sh_isoption(SH_POSIX) && n=='>' && (sh_isoption(SH_BASH) || sh_isstate(SH_PROFILE))) + if(n=='>' && !sh_isoption(SH_POSIX)) { - if(!sh_isoption(SH_BASH) && !lp->nonstandard) - { - lp->nonstandard = 1; - errormsg(SH_DICT,ERROR_warn(0),e_lexnonstandard,shp->inlineno); - } + /* bash-style "&>file" shorthand for ">file 2>&1" */ lp->digits = -1; c = '>'; } diff --git a/src/cmd/ksh93/sh/main.c b/src/cmd/ksh93/sh/main.c index 2670a280e..8078da34f 100644 --- a/src/cmd/ksh93/sh/main.c +++ b/src/cmd/ksh93/sh/main.c @@ -163,7 +163,6 @@ int sh_main(int ac, char *av[], Shinit_f userinit) if((beenhere++)==0) { sh_onstate(SH_PROFILE); - ((Lex_t*)shp->lex_context)->nonstandard = 0; if(shp->gd->ppid==1) shp->login_sh++; if(shp->login_sh >= 2) @@ -177,12 +176,14 @@ int sh_main(int ac, char *av[], Shinit_f userinit) sh_onoption(SH_BGNICE); sh_onoption(SH_RC); } - if(!sh_isoption(SH_RC) && (sh_isoption(SH_BASH) && !sh_isoption(SH_POSIX) #if SHOPT_REMOTE - || !fstat(0, &statb) && REMOTE(statb.st_mode) -#endif - )) + /* + * Building ksh with SHOPT_REMOTE=1 causes ksh to set --rc if stdin is + * a socket (presumably part of a remote shell invocation.) + */ + if(!sh_isoption(SH_RC) && !fstat(0, &statb) && REMOTE(statb.st_mode)) sh_onoption(SH_RC); +#endif for(i=0; ioffoptions.v); i++) shp->options.v[i] &= ~shp->offoptions.v[i]; if(sh_isoption(SH_INTERACTIVE)) @@ -212,28 +213,16 @@ int sh_main(int ac, char *av[], Shinit_f userinit) { if(!sh_isoption(SH_NOUSRPROFILE) && !sh_isoption(SH_PRIVILEGED) && sh_isoption(SH_RC)) { -#if SHOPT_BASH - if(sh_isoption(SH_BASH) && !sh_isoption(SH_POSIX)) - { + if(name = sh_mactry(shp,nv_getval(ENVNOD))) + name = *name ? strdup(name) : (char*)0; #if SHOPT_SYSRC - sh_source(shp, iop, e_bash_sysrc); -#endif - sh_source(shp, iop, shp->gd->rcfile ? shp->gd->rcfile : sh_mactry(shp,(char*)e_bash_rc)); - } - else + if(!strmatch(name, "?(.)/./*")) + sh_source(shp, iop, e_sysrc); #endif + if(name) { - if(name = sh_mactry(shp,nv_getval(ENVNOD))) - name = *name ? strdup(name) : (char*)0; -#if SHOPT_SYSRC - if(!strmatch(name, "?(.)/./*")) - sh_source(shp, iop, e_sysrc); -#endif - if(name) - { - sh_source(shp, iop, name); - free(name); - } + sh_source(shp, iop, name); + free(name); } } else if(sh_isoption(SH_INTERACTIVE) && sh_isoption(SH_PRIVILEGED)) diff --git a/src/cmd/ksh93/sh/name.c b/src/cmd/ksh93/sh/name.c index 670071ce7..c3fe583e7 100644 --- a/src/cmd/ksh93/sh/name.c +++ b/src/cmd/ksh93/sh/name.c @@ -549,7 +549,7 @@ void nv_setlist(register struct argnod *arg,register int flags, Namval_t *typ) { if(!(arg->argflag&ARG_APPEND)) _nv_unset(np,NV_EXPORT); - if(!sh_isoption(SH_BASH) && !(array&NV_IARRAY) && !nv_isarray(np)) + if(!(array&NV_IARRAY) && !nv_isarray(np)) nv_setarray(np,nv_associative); } skip: diff --git a/src/cmd/ksh93/sh/xec.c b/src/cmd/ksh93/sh/xec.c index 6eacb6432..6c620badd 100644 --- a/src/cmd/ksh93/sh/xec.c +++ b/src/cmd/ksh93/sh/xec.c @@ -1086,19 +1086,6 @@ int sh_exec(register const Shnode_t *t, int flags) } if(np) flgs |= NV_UNJUST; -#if SHOPT_BASH - if(np==SYSLOCAL) - { - if(!nv_getval(SH_FUNNAMENOD)) - errormsg(SH_DICT,ERROR_exit(1),"%s: can only be used in a function",com0); - if(!shp->st.var_local) - { - sh_scope(shp,(struct argnod*)0,0); - shp->st.var_local = shp->var_tree; - } - - } -#endif /* SHOPT_BASH */ if(np && np->nvalue.bfp==SYSTYPESET->nvalue.bfp) { /* command calls b_typeset(); treat as a typeset variant */ @@ -1134,7 +1121,7 @@ int sh_exec(register const Shnode_t *t, int flags) } #endif /* SHOPT_TYPEDEF */ - if((shp->fn_depth && !shp->prefix) || np==SYSLOCAL) + if((shp->fn_depth && !shp->prefix)) flgs |= NV_NOSCOPE; } else if(np==SYSEXPORT) diff --git a/src/cmd/ksh93/tests/io.sh b/src/cmd/ksh93/tests/io.sh index cf37d0ce5..f2c53ee14 100755 --- a/src/cmd/ksh93/tests/io.sh +++ b/src/cmd/ksh93/tests/io.sh @@ -597,5 +597,24 @@ then trap 'sleep_pid=0; kill "$ksh_pid"; err_exit "'\''read'\'' hangs on EOF wit else err_exit "mkfifo failed; cannot test reading from FIFO" fi +# ====== +# "&>file" redirection operator, shorthand for ">file 2>&1" (new as of 93u+m; inherited from old SHOPT_BASH) +if [[ -o ?posix ]] +then set -o posix + # This should print in a background job, then create an empty file, as '>aha1.txt' is a separate command. + eval ' print -u1 bad1 &>aha1.txt + print -u2 bad2 &>aha2.txt + ' >/dev/null 2>&1 + [[ -s aha1.txt ]] && err_exit "&> not deactivated in POSIX mode (stdout; got '$(cat aha1.txt)')" + [[ -s aha2.txt ]] && err_exit "&> not deactivated in POSIX mode (stderr; got '$(cat aha2.txt)')" + set +o posix + # This should write the text to the file. + eval ' print -u1 ok1 &>aha1.txt + print -u2 ok2 &>aha2.txt + ' >/dev/null 2>&1 + [[ $(< aha1.txt) == ok1 ]] || err_exit '&> does not redirect stdout' + [[ $(< aha2.txt) == ok2 ]] || err_exit '&> does not redirect stderr' +fi + # ====== exit $((Errors<125?Errors:125)) diff --git a/src/cmd/ksh93/tests/options.sh b/src/cmd/ksh93/tests/options.sh index 28eb7df43..bd15e56b4 100755 --- a/src/cmd/ksh93/tests/options.sh +++ b/src/cmd/ksh93/tests/options.sh @@ -53,28 +53,9 @@ then err_exit 'sh -e not working' fi [[ $($SHELL -D -c 'print hi; print $"hello"') == '"hello"' ]] || err_exit 'ksh -D not working' -env=$tmp/.env -print $'(print -u1 aha) &>/dev/null\n(print -u2 aha) &>/dev/null' > $env rc=$tmp/.kshrc print $'PS1=""\nfunction env_hit\n{\n\tprint OK\n}' > $rc -export ENV=/.$env -if [[ ! -o privileged ]] -then - got=$($SHELL -E -c : 2>/dev/null) - if [[ $g ]] - then - got=$(printf %q "$got") - err_exit "\$ENV file &>/dev/null does not redirect stdout -- expected '', got $got" - fi - got=$(set +x; $SHELL -E -c : 2>&1 >/dev/null) - if [[ $got != *nonstandard* || $got == *$'\n'* ]] - then - got=$(printf %q "$got") - err_exit "\$ENV file &>/dev/null does not redirect stderr -- expected one diagnostic line, got $got" - fi -fi - export ENV=/.$rc if [[ -o privileged ]] then