1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-02-13 11:42:21 +00:00

Remove SHOPT_BASH; keep &> redir operator, '-o posix' option

On 16 June there was a call for volunteers to fix the bash
compatibility mode; it has never successfully compiled in 93u+.
Since no one showed up, it is now removed due to lack of interest.

A couple of things are kept, which are now globally enabled:

1. The &>file redirection shorthand (for >file 2>&1). As a matter
   of fact, ksh93 already supported this natively, but only while
   running rc/profile/login scripts, and it issued a warning. This
   makse it globally available and removes the warning, bringing
   ksh93 in line with mksh, bash and zsh.

2. The '-o posix' standard compliance option. It is now enabled on
   startup if ksh is invoked as 'sh' or if the POSIXLY_CORRECT
   variable exists in the environment. To begin with, it disables
   the aforementioned &> redirection shorthand. Further compliance
   tweaks will be added in subsequent commits. The differences will
   be fairly minimal as ksh93 is mostly compliant already.

In all changed files, code was removed that was compiled (more
precisely, failed to compile/link) if the SHOPT_BASH preprocessor
identifier was defined. Below are other changes worth mentioning:

src/cmd/ksh93/sh/bash.c,
src/cmd/ksh93/data/bash_pre_rc.sh:
- Removed.

src/cmd/ksh93/data/lexstates.c,
src/cmd/ksh93/include/shlex.h,
src/cmd/ksh93/sh/lex.c:
- Globally enable &> redirection operator if SH_POSIX not active.
- Remove warning that was issued when &> was used in rc scripts.

src/cmd/ksh93/data/options.c,
src/cmd/ksh93/include/defs.h,
src/cmd/ksh93/sh/args.c:
- Keep SH_POSIX option (-o posix).
- Replace SH_TYPE_BASH shell type by SH_TYPE_POSIX.

src/cmd/ksh93/sh/init.c:
- sh_type(): Return SH_TYPE_POSIX shell type if ksh was invoked
  as sh (or rsh, restricted sh).
- sh_init(): Enable posix option if the SH_TYPE_POSIX shell type
  was detected, or if the CONFORMANCE ast config variable was set
  to "standard" (which libast sets on init if POSIXLY_CORRECT
  exists in the environment).

src/cmd/ksh93/tests/options.sh,
src/cmd/ksh93/tests/io.sh:
- Replace regression tests for &> and move to io.sh. Since &> is
  now for general use, no longer test in an rc script, and don't
  check that a warning is issued.

Closes: #9
Progresses: #20
This commit is contained in:
Martijn Dekker 2020-09-01 06:19:19 +01:00
parent 84331a96fc
commit 921bbcaeb7
25 changed files with 95 additions and 1148 deletions

12
NEWS
View file

@ -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. 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: 2020-08-19:
- Sped up the 'read' command on most systems by 15-25%. Fixed a hanging bug - Sped up the 'read' command on most systems by 15-25%. Fixed a hanging bug

View file

@ -43,10 +43,6 @@ Directory layout:
fixes and new features since the original ksh93 release. The file fixes and new features since the original ksh93 release. The file
COMPATIBILITY is a list of all known incompatibilities with ksh88. 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: Include directory:
1. argnod.h contains the type definitions for command 1. argnod.h contains the type definitions for command
nodes, io nodes, argument nodes, and for positional nodes, io nodes, argument nodes, and for positional
@ -111,8 +107,7 @@ sh directory:
library and the interface to shell arithmetic. library and the interface to shell arithmetic.
3. array.c contains the code for indexed and associative 3. array.c contains the code for indexed and associative
arrays. arrays.
4. bash.c contains code used when compiling with SHOPT_BASH 4. (removed)
to add bash specific features such as shopt.
5. defs.c contains the data definitions for global symbols. 5. defs.c contains the data definitions for global symbols.
6. deparse.c contains code to generate shell script from 6. deparse.c contains code to generate shell script from
a parse tree. a parse tree.

View file

@ -20,7 +20,6 @@ SHOPT_ACCT == /* accounting */
SHOPT_ACCTFILE == /* per user accounting info */ SHOPT_ACCTFILE == /* per user accounting info */
SHOPT_AUDIT == 1 /* enable auditing per SHOPT_AUDITFILE */ SHOPT_AUDIT == 1 /* enable auditing per SHOPT_AUDITFILE */
SHOPT_AUDITFILE == "/etc/ksh_audit" /* auditing file */ SHOPT_AUDITFILE == "/etc/ksh_audit" /* auditing file */
SHOPT_BASH == /* bash compatibility code */
SHOPT_BGX == 1 /* one SIGCHLD trap per completed job */ SHOPT_BGX == 1 /* one SIGCHLD trap per completed job */
SHOPT_BRACEPAT == 1 /* C-shell {...,...} expansions (, required) */ SHOPT_BRACEPAT == 1 /* C-shell {...,...} expansions (, required) */
SHOPT_CMDLIB_HDR == /* -lcmd builtin list (<cmdlist.h>) */ SHOPT_CMDLIB_HDR == /* -lcmd builtin list (<cmdlist.h>) */
@ -98,11 +97,6 @@ if CC.HOSTTYPE == "win32*"
SHOPT_CRNL == 1 /* <cr><nl> is equivalent to <nl> */ SHOPT_CRNL == 1 /* <cr><nl> is equivalent to <nl> */
end 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 */ /* use the following libraries only if they exist */
LIBS_opt := +ljobs +li LIBS_opt := +ljobs +li
@ -136,10 +130,6 @@ end
if SHOPT_VSH if SHOPT_VSH
FILES_opt += vi.c FILES_opt += vi.c
end end
if SHOPT_BASH
FILES_opt += bash.c bash_pre_rc.c
SHOPT_HISTEXPAND == 1
end
if SHOPT_HISTEXPAND if SHOPT_HISTEXPAND
FILES_opt += hexpand.c FILES_opt += hexpand.c
end end
@ -150,7 +140,7 @@ if SHOPT_X
LDFLAGS += -u _XtAppInitialize -L/usr/add-on/X11/lib LDFLAGS += -u _XtAppInitialize -L/usr/add-on/X11/lib
end 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) $(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=?) 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) \ :: 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 shopen.mk shopen.c
:: shtests \ :: shtests \

View file

@ -645,7 +645,7 @@ prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
done sh/main.c done sh/main.c
meta main.o %.c>%.o sh/main.c main meta main.o %.c>%.o sh/main.c main
prev sh/main.c 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 done main.o generated
make nvdisc.o make nvdisc.o
make sh/nvdisc.c make sh/nvdisc.c
@ -1101,7 +1101,7 @@ prev include/defs.h implicit
done sh/trestore.c done sh/trestore.c
meta trestore.o %.c>%.o sh/trestore.c trestore meta trestore.o %.c>%.o sh/trestore.c trestore
prev sh/trestore.c 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 done trestore.o generated
make waitevent.o make waitevent.o
make sh/waitevent.c make sh/waitevent.c
@ -1189,7 +1189,7 @@ prev ${PACKAGE_ast_INCLUDE}/ast_standards.h implicit
done data/strdata.c done data/strdata.c
meta strdata.o %.c>%.o data/strdata.c strdata meta strdata.o %.c>%.o data/strdata.c strdata
prev data/strdata.c 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 done strdata.o generated
make testops.o make testops.o
make data/testops.c make data/testops.c

View file

@ -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 <dgk@research.att.com> #
# #
########################################################################
#
# bash compatibility startup script
#
# Author:
# Karsten Fleischer
# Omnium Software Engineering
# An der Luisenburg 7
# D-51379 Leverkusen
# Germany
#
# <K.Fleischer@omnium.de>
#
alias declare=typeset
nameref FUNCNAME=.sh.fun
integer SHLVL
export SHLVL
SHLVL+=1
if [[ ! $EUID ]]
then EUID=$(id -u)
readonly EUID
fi
if [[ ! $UID ]]
then UID=$(id -u)
readonly UID
fi
readonly SHELLOPTS
if ! shopt -qo restricted; then
IFS=:
for i in $SHELLOPTS
do
[[ -n "$i" ]] && set -o $i
done
unset IFS
fi
function SHELLOPTS.get
{
.sh.value=$(shopt -so)
.sh.value=${.sh.value//+([[:space:]])on*([[:space:]])/:}
.sh.value=${.sh.value%:}
}
set -A GROUPS $(id -G)
function GROUPS.set
{
return 1
}
function GROUPS.unset
{
unset -f GROUPS.set
unset -f GROUPS.unset
}
typeset -A DIRSTACK
function DIRSTACK.get
{
set -A .sh.value $(dirs)
}
function DIRSTACK.set
{
integer index
index=_push_max-.sh.subscript
(( index == _push_max || index < _push_top )) && return
_push_stack[index]=${.sh.value}
}
function DIRSTACK.unset
{
unset -f DIRSTACK.get
unset -f DIRSTACK.set
unset -f DIRSTACK.unset
}
function PS1.set
{
typeset prefix remaining=${.sh.value} var= n= k=
while [[ $remaining ]]
do prefix=${remaining%%'\'*}
remaining=${remaining#$prefix}
var+="$prefix"
case ${remaining:1:1} in
t) var+="\$(printf '%(%H:%M:%S)T')";;
d) var+="\$(printf '%(%a %b:%e)T')";;
n) var+=$'\n';;
s) var+=ksh;;
w) var+="\$(pwd)";;
W) var+="\$(basename \"\$(pwd)\")";;
u) var+=$USER;;
h) var+=$(hostname -s);;
'#') var+=!;;
!) var+=!;;
@) var+="\$(printf '%(%I:%M%p)T')";;
'$') if (( $(id -u) == 0 ))
then var+='#'
else var+='$'
fi;;
'\') var+='\\';;
'['|']') ;;
[0-7]) case ${remaining:1:3} in
[0-7][0-7][0-7])
k=4;;
[0-7][0-7])
k=3;;
*) k=2;;
esac
eval n="\$'"${remaining:0:k}"'"
var+=$n
remaining=${remaining:k}
continue
;;
"") ;;
*) var+='\'${remaining:0:2};;
esac
remaining=${remaining:2}
done
.sh.value=$var
}
function logout
{
if shopt -q login_shell; then
exit
else
print ${BASH##*/}: $0: not login shell: use 'exit' >&2
return 1
fi
}
PS1="bash$ "
function source
{
if ! shopt -qpo posix; then
unset OPATH
typeset OPATH=$PATH
typeset PATH=$PATH
if shopt -q sourcepath; then
PATH=$OPATH:.
else
PATH=.
fi
fi
. "$@"
}
unalias .
alias .=source
alias enable=builtin
function help
{
typeset b cmd usage try_cmd man
function has_help_option
{
[[ $1 == @(''|/*|:|echo|false|true|login|test|'[') ]] && return 1
return 0
}
typeset -A short_use=(
[echo]='Usage: echo [ options ] [arg]...'
[:]='Usage: : ...'
[true]='Usage: true ...'
[false]='Usage: false ...'
[login]='Usage: login [-p] [name]'
['[']='Usage: [ EXPRESSION ] | [ OPTION'
[test]='Usage: test EXPRESSION | test'
)
b=$(builtin)
if (( $# == 0))
then print 'The following is the current list of built-in commands:'
print -r $'Type help *name* for more information about name\n'
for cmd in $b
do if has_help_option $cmd
then usage=$($cmd --short 2>&1)
print -r -- "${usage:7}"
else print -r -- ${short_use[$cmd]:7}
fi
done
return
fi
b=${b/'['/}
man=--man
[[ $1 == -s ]] && man=--short && shift
for try_cmd
do if has_help_option $try_cmd
then if [[ $try_cmd == @(${b//$'\n'/'|'}) ]]
then $try_cmd $man
else man $try_cmd
fi
elif [[ $man == '--short' ]]
then print -r -- ${short_use[$try_cmd]}
else man $try_cmd
fi
done
}
function cd
{
local msg
local args
local i
local a
local ret
if ! shopt -q cdable_vars; then
command cd "$@"
else
msg=$(command cd "$@" 2>&1)
ret=$?
if [[ $ret != 0 ]]; then
for i
do
case $i in
-*) args="$args $i" ;;
*/*) args="$args $i" ;;
*) eval a="$"$i
if [[ -n $a ]]; then args="$args $a"
else args="$args $i"
fi
;;
esac
done
command cd $args
else
print -- $msg
return $ret
fi
fi
}
typeset BASH=$0
! shopt -qo posix && HISTFILE=~/.bash_history
HOSTNAME=$(hostname)
nameref BASH_SUBSHELL=.sh.subshell

View file

@ -54,7 +54,6 @@
/* /*
* IMPORTANT: The order of these struct members must be synchronous * IMPORTANT: The order of these struct members must be synchronous
* with the offsets on the macros defined in include/builtins.h! * with the offsets on the macros defined in include/builtins.h!
* The order up through "local" is significant.
*/ */
const struct shtable3 shtab_builtins[] = const struct shtable3 shtab_builtins[] =
{ {
@ -81,9 +80,6 @@ const struct shtable3 shtab_builtins[] =
".", NV_BLTIN|BLT_ENV|BLT_SPC, bltin(dot_cmd), ".", NV_BLTIN|BLT_ENV|BLT_SPC, bltin(dot_cmd),
"source", NV_BLTIN|BLT_ENV, bltin(dot_cmd), "source", NV_BLTIN|BLT_ENV, bltin(dot_cmd),
"return", NV_BLTIN|BLT_ENV|BLT_SPC, bltin(return), "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. * 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 " "[+gmacs?Enables/disables \bgmacs\b editing mode. \bgmacs\b "
"editing mode is the same as \bemacs\b editing mode " "editing mode is the same as \bemacs\b editing mode "
"except for the handling of \b^T\b.]" "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 #if SHOPT_HISTEXPAND
"[+histexpand?Equivalent to \b-H\b.]" "[+histexpand?Equivalent to \b-H\b.]"
#endif #endif
@ -247,20 +236,12 @@ const char sh_set[] =
"compatibility.]" "compatibility.]"
"[+notify?Equivalent to \b-b\b.]" "[+notify?Equivalent to \b-b\b.]"
"[+nounset?Equivalent to \b-u\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 " "[+pipefail?A pipeline will not complete until all components "
"of the pipeline have completed, and the exit status " "of the pipeline have completed, and the exit status "
"of the pipeline will be the value of the last " "of the pipeline will be the value of the last "
"command to exit with non-zero exit status, or will " "command to exit with non-zero exit status, or will "
"be zero if all commands return zero exit status.]" "be zero if all commands return zero exit status.]"
"[+posix?Enable POSIX standard compatibility mode.]"
"[+privileged?Equivalent to \b-p\b.]" "[+privileged?Equivalent to \b-p\b.]"
"[+rc?Do not run the \b.kshrc\b file for interactive shells.]" "[+rc?Do not run the \b.kshrc\b file for interactive shells.]"
"[+showme?Simple commands preceded by a \b;\b will be traced " "[+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 " "[x?Execution trace. The shell will display each command after all "
"expansion and before execution preceded by the expanded value " "expansion and before execution preceded by the expanded value "
"of the \bPS4\b parameter.]" "of the \bPS4\b parameter.]"
#if SHOPT_BASH
"\fbash1\f"
#endif
#if SHOPT_BRACEPAT #if SHOPT_BRACEPAT
"[B?Enable {...} group expansion. On by default.]" "[B?Enable {...} group expansion. On by default.]"
#endif #endif
@ -1569,9 +1547,6 @@ USAGE_LICENSE
"[I:regress]:[intercept?Enable the regression test \aintercept\a. Must be " "[I:regress]:[intercept?Enable the regression test \aintercept\a. Must be "
"the first command line option(s).]" "the first command line option(s).]"
#endif #endif
#if SHOPT_BASH
"\fbash2\f"
#endif
"\fabc\f" "\fabc\f"
"?" "?"
"[T?Enable implementation specific test code defined by mask.]#[mask]" "[T?Enable implementation specific test code defined by mask.]#[mask]"

View file

@ -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_lexobsolete4[] = "line %d: %s within [[...]] obsolete, use ((...))";
const char e_lexobsolete5[] = "line %d: set %s obsolete"; const char e_lexobsolete5[] = "line %d: set %s obsolete";
const char e_lexobsolete6[] = "line %d: `{' instead of `in' is 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_lexusebrace[] = "line %d: use braces to avoid ambiguities with $id[...]";
const char e_lexusequote[] = "line %d: %c within ${} should be quoted"; const char e_lexusequote[] = "line %d: %c within ${} should be quoted";
const char e_lexescape[] = "line %d: escape %c to avoid ambiguities"; const char e_lexescape[] = "line %d: escape %c to avoid ambiguities";

View file

@ -187,15 +187,6 @@ const char e_suidprofile[] = "/etc/suid_profile";
#if SHOPT_SYSRC #if SHOPT_SYSRC
const char e_sysrc[] = "/etc/ksh.kshrc"; const char e_sysrc[] = "/etc/ksh.kshrc";
#endif #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_crondir[] = "/usr/spool/cron/atjobs";
const char e_prohibited[] = "login setuid/setgid shells prohibited"; const char e_prohibited[] = "login setuid/setgid shells prohibited";
#ifdef BUILD_DTKSH #ifdef BUILD_DTKSH

View file

@ -23,14 +23,6 @@
#include "name.h" #include "name.h"
#include "shtable.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 is the list of invocation and set options
* This list must be in in ascii sorted order * This list must be in in ascii sorted order
@ -39,83 +31,42 @@
const Shtable_t shtab_options[] = const Shtable_t shtab_options[] =
{ {
"allexport", SH_ALLEXPORT, "allexport", SH_ALLEXPORT,
#if SHOPT_BASH
"bash", (SH_BASH|SH_COMMANDLINE),
#endif
"bgnice", SH_BGNICE, "bgnice", SH_BGNICE,
"braceexpand", SH_BRACEEXPAND, "braceexpand", SH_BRACEEXPAND,
bashopt("cdable_vars", SH_CDABLE_VARS)
bashopt("cdspell", SH_CDSPELL)
bashopt("checkhash", SH_CHECKHASH)
bashopt("checkwinsize", SH_CHECKWINSIZE)
"noclobber", SH_NOCLOBBER, "noclobber", SH_NOCLOBBER,
bashopt("dotglob", SH_DOTGLOB)
"emacs", SH_EMACS, "emacs", SH_EMACS,
"errexit", SH_ERREXIT, "errexit", SH_ERREXIT,
"noexec", SH_NOEXEC, "noexec", SH_NOEXEC,
bashopt("execfail", SH_EXECFAIL)
bashopt("expand_aliases", SH_EXPAND_ALIASES)
bashopt("extglob", SH_EXTGLOB)
"noglob", SH_NOGLOB, "noglob", SH_NOGLOB,
"globstar", SH_GLOBSTARS, "globstar", SH_GLOBSTARS,
"gmacs", SH_GMACS, "gmacs", SH_GMACS,
bashextra("hashall", SH_TRACKALL)
bashopt("histappend", SH_HISTAPPEND)
#if SHOPT_HISTEXPAND #if SHOPT_HISTEXPAND
"histexpand", SH_HISTEXPAND, "histexpand", SH_HISTEXPAND,
#else
bashextra("histexpand", SH_HISTEXPAND)
#endif #endif
bashextra("history", SH_HISTORY2)
bashopt("histreedit", SH_HISTREEDIT)
bashopt("histverify", SH_HISTVERIFY)
bashopt("hostcomplete", SH_HOSTCOMPLETE)
bashopt("huponexit", SH_HUPONEXIT)
"ignoreeof", SH_IGNOREEOF, "ignoreeof", SH_IGNOREEOF,
"interactive", SH_INTERACTIVE|SH_COMMANDLINE, "interactive", SH_INTERACTIVE|SH_COMMANDLINE,
bashextra("interactive_comments", SH_INTERACTIVE_COMM)
"keyword", SH_KEYWORD, "keyword", SH_KEYWORD,
"letoctal", SH_LETOCTAL, "letoctal", SH_LETOCTAL,
bashopt("lithist", SH_LITHIST)
"nolog", SH_NOLOG, "nolog", SH_NOLOG,
"login_shell", SH_LOGIN_SHELL|SH_COMMANDLINE, "login_shell", SH_LOGIN_SHELL|SH_COMMANDLINE,
bashopt("mailwarn", SH_MAILWARN)
"markdirs", SH_MARKDIRS, "markdirs", SH_MARKDIRS,
"monitor", SH_MONITOR, "monitor", SH_MONITOR,
"multiline", SH_MULTILINE, "multiline", SH_MULTILINE,
bashopt("no_empty_cmd_completion", SH_NOEMPTYCMDCOMPL)
bashopt("nocaseglob", SH_NOCASEGLOB)
"notify", SH_NOTIFY, "notify", SH_NOTIFY,
bashopt("nullglob", SH_NULLGLOB)
bashextra("onecmd", SH_TFLAG)
"pipefail", SH_PIPEFAIL, "pipefail", SH_PIPEFAIL,
bashextra("physical", SH_PHYSICAL) "posix", SH_POSIX,
bashextra("posix", SH_POSIX)
"privileged", SH_PRIVILEGED, "privileged", SH_PRIVILEGED,
#if SHOPT_BASH #if SHOPT_PFSH
"profile", SH_LOGIN_SHELL|SH_COMMANDLINE,
# if SHOPT_PFSH
"pfsh", SH_PFSH|SH_COMMANDLINE,
# endif
#else
# if SHOPT_PFSH
"profile", SH_PFSH|SH_COMMANDLINE, "profile", SH_PFSH|SH_COMMANDLINE,
# endif
#endif #endif
bashopt("progcomp", SH_PROGCOMP)
bashopt("promptvars", SH_PROMPTVARS)
"rc", SH_RC|SH_COMMANDLINE, "rc", SH_RC|SH_COMMANDLINE,
"restricted", SH_RESTRICTED, "restricted", SH_RESTRICTED,
bashopt("restricted_shell", SH_RESTRICTED2|SH_COMMANDLINE)
bashopt("shift_verbose", SH_SHIFT_VERBOSE)
"showme", SH_SHOWME, "showme", SH_SHOWME,
bashopt("sourcepath", SH_SOURCEPATH)
"trackall", SH_TRACKALL, "trackall", SH_TRACKALL,
"nounset", SH_NOUNSET, "nounset", SH_NOUNSET,
"verbose", SH_VERBOSE, "verbose", SH_VERBOSE,
"vi", SH_VI, "vi", SH_VI,
"viraw", SH_VIRAW, "viraw", SH_VIRAW,
bashopt("xpg_echo", SH_XPG_ECHO)
"xtrace", SH_XTRACE, "xtrace", SH_XTRACE,
"", 0 "", 0
}; };

View file

@ -58,11 +58,6 @@
#define SYSDOT (shgd->bltin_cmds+20) /* . */ #define SYSDOT (shgd->bltin_cmds+20) /* . */
#define SYSSOURCE (shgd->bltin_cmds+21) /* source */ #define SYSSOURCE (shgd->bltin_cmds+21) /* source */
#define SYSRETURN (shgd->bltin_cmds+22) /* return */ #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 */ /* entry point for shell special builtins */

View file

@ -311,7 +311,6 @@ struct shared
#define SH_COMPLETE 19 /* set for command completion */ #define SH_COMPLETE 19 /* set for command completion */
#define SH_INTESTCMD 20 /* set while test/[ command is being run */ #define SH_INTESTCMD 20 /* set while test/[ command is being run */
#define SH_BASH 41
#define SH_BRACEEXPAND 42 #define SH_BRACEEXPAND 42
#define SH_POSIX 46 #define SH_POSIX 46
#define SH_MULTILINE 47 #define SH_MULTILINE 47
@ -319,9 +318,7 @@ struct shared
#define SH_NOPROFILE 78 #define SH_NOPROFILE 78
#define SH_NOUSRPROFILE 79 #define SH_NOUSRPROFILE 79
#define SH_LOGIN_SHELL 67 #define SH_LOGIN_SHELL 67
#define SH_COMMANDLINE 0x100 #define SH_COMMANDLINE 0x100 /* flag for invocation-only options ('set -o' cannot change them) */
#define SH_BASHEXTRA 0x200
#define SH_BASHOPT 0x400
#define SH_ID "ksh" /* ksh id */ #define SH_ID "ksh" /* ksh id */
#define SH_STD "sh" /* standard sh id */ #define SH_STD "sh" /* standard sh id */
@ -330,44 +327,11 @@ struct shared
#define SH_TYPE_SH 001 #define SH_TYPE_SH 001
#define SH_TYPE_KSH 002 #define SH_TYPE_KSH 002
#define SH_TYPE_BASH 004 #define SH_TYPE_POSIX 004
#define SH_TYPE_LOGIN 010 #define SH_TYPE_LOGIN 010
#define SH_TYPE_PROFILE 020 #define SH_TYPE_PROFILE 020
#define SH_TYPE_RESTRICTED 040 #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 #if SHOPT_HISTEXPAND
# define SH_HISTAPPEND 60 # define SH_HISTAPPEND 60
# define SH_HISTEXPAND 43 # define SH_HISTEXPAND 43
@ -483,7 +447,6 @@ extern const char e_dict[];
#define PRINT_VERBOSE 0x01 /* option on|off list */ #define PRINT_VERBOSE 0x01 /* option on|off list */
#define PRINT_ALL 0x02 /* list unset options too */ #define PRINT_ALL 0x02 /* list unset options too */
#define PRINT_NO_HEADER 0x04 /* omit listing header */ #define PRINT_NO_HEADER 0x04 /* omit listing header */
#define PRINT_SHOPT 0x08 /* shopt -s|-u */
#define PRINT_TABLE 0x10 /* table of all options */ #define PRINT_TABLE 0x10 /* table of all options */
#ifdef SHOPT_STATS #ifdef SHOPT_STATS

View file

@ -114,15 +114,6 @@ extern const char e_sysprofile[];
#if SHOPT_SYSRC #if SHOPT_SYSRC
extern const char e_sysrc[]; extern const char e_sysrc[];
#endif #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_stdprompt[];
extern const char e_supprompt[]; extern const char e_supprompt[];
extern const char e_ambiguous[]; extern const char e_ambiguous[];

View file

@ -41,7 +41,6 @@ typedef struct _shlex_
int lastline; /* last line number */ int lastline; /* last line number */
int lasttok; /* previous token number */ int lasttok; /* previous token number */
int digits; /* numerical value with word token */ int digits; /* numerical value with word token */
int nonstandard; /* nonstandard construct in profile */
char aliasok; /* on when alias is legal */ char aliasok; /* on when alias is legal */
char assignok; /* on when name=value is legal */ char assignok; /* on when name=value is legal */
char inexec; /* on when processing exec */ char inexec; /* on when processing exec */

View file

@ -17,4 +17,4 @@
* David Korn <dgk@research.att.com> * * David Korn <dgk@research.att.com> *
* * * *
***********************************************************************/ ***********************************************************************/
#define SH_RELEASE "93u+m 2020-08-19" #define SH_RELEASE "93u+m 2020-09-01"

View file

@ -3409,7 +3409,7 @@ successfully rename it to
otherwise, delete the temporary file. otherwise, delete the temporary file.
.BI >; word .BI >; word
cannot be used with the cannot be used with the
.IR exec (2). .IR exec
built-in. built-in.
.TP .TP
.BI >> word .BI >> word
@ -3433,7 +3433,7 @@ except that if the command completes successfully,
is truncated to the offset at command completion. is truncated to the offset at command completion.
.BI <>; word .BI <>; word
cannot be used with the cannot be used with the
.IR exec (2). .IR exec
built-in. built-in.
.TP .TP
\f3<<\fP\*(OK\f3\-\fP\*(CK\f2word\fP \f3<<\fP\*(OK\f3\-\fP\*(CK\f2word\fP
@ -3492,20 +3492,26 @@ The standard input is duplicated from file descriptor
.I digit .I digit
(see (see
.IR dup (2)). .IR dup (2)).
Similarly for the standard output using .TP
\f3>&\^\f2digit\fR. .BI >& digit
The standard output is duplicated from file descriptor
.IR digit .
.TP .TP
.BI <& digit \- .BI <& digit \-
The file descriptor given by The file descriptor given by
.I digit .I digit
is moved to standard input. is moved to standard input.
Similarly for the standard output using .TP
\f3>&\^\f2digit\f3\-\fR. .BI >& digit \-
The file descriptor given by
.I digit
is moved to standard output.
.TP .TP
.B <&\- .B <&\-
The standard input is closed. The standard input is closed.
Similarly for the standard output using .TP
.BR >&\- . .B >&\-
The standard output is closed.
.TP .TP
.B <&p .B <&p
The input from the co-process is moved to standard input. 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 the file descriptor number in variable
.BR n . .BR n .
.PP .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 order in which redirections are specified is significant.
The shell evaluates each redirection in terms of the The shell evaluates each redirection in terms of the
.RI ( "file descriptor" ", " file ) .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 will be the value of the last non-zero command
to fail or zero if no command has failed. to fail or zero if no command has failed.
.TP 8 .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 .B privileged
Same as Same as
.BR \-p . .BR \-p .

View file

@ -42,11 +42,6 @@
#else #else
# define PFSHOPT # define PFSHOPT
#endif #endif
#if SHOPT_BASH
# define BASHOPT "\374"
#else
# define BASHOPT
#endif
#if SHOPT_HISTEXPAND #if SHOPT_HISTEXPAND
# define HFLAG "H" # define HFLAG "H"
#else #else
@ -59,15 +54,13 @@
static char *null; static char *null;
/* The following order is determined by sh_optset */ /* 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[] = static const int flagval[] =
{ {
#if SHOPT_PFSH #if SHOPT_PFSH
SH_PFSH, SH_PFSH,
#endif #endif
#if SHOPT_BASH
SH_POSIX, SH_POSIX,
#endif
SH_DICTIONARY, SH_INTERACTIVE, SH_RESTRICTED, SH_CFLAG, SH_DICTIONARY, SH_INTERACTIVE, SH_RESTRICTED, SH_CFLAG,
SH_ALLEXPORT, SH_NOTIFY, SH_ERREXIT, SH_NOGLOB, SH_TRACKALL, SH_ALLEXPORT, SH_NOTIFY, SH_ERREXIT, SH_NOGLOB, SH_TRACKALL,
SH_KEYWORD, SH_MONITOR, SH_NOEXEC, SH_PRIVILEGED, SH_SFLAG, SH_TFLAG, 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) 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!=':') if(*s!=':')
sfputr(sp,sh_set,-1); sfputr(sp,sh_set,-1);
return(1); return(1);
@ -168,31 +145,17 @@ int sh_argopts(int argc,register char *argv[], void *context)
if(f) if(f)
nv_unset(np); nv_unset(np);
continue; 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 */ case 'o': /* set options */
byname: byname:
if(!opt_info.arg||!*opt_info.arg||*opt_info.arg=='-') if(!opt_info.arg||!*opt_info.arg||*opt_info.arg=='-')
{ {
action = PRINT; action = PRINT;
/* print style: -O => shopt options
* bash => print unset options also, no heading
*/
verbose = (f?PRINT_VERBOSE:PRINT_NO_HEADER)| 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); ((opt_info.arg&&(!*opt_info.arg||*opt_info.arg=='-'))?(PRINT_TABLE|PRINT_NO_HEADER):0);
continue; continue;
} }
o = sh_lookopt(opt_info.arg,&f); o = sh_lookopt(opt_info.arg,&f);
if(o<=0 if(o<=0 || (setflag && (o&SH_COMMANDLINE)))
|| (!sh_isoption(SH_BASH) && (o&SH_BASHEXTRA))
|| ((!sh_isoption(SH_BASH) || n=='o') && (o&SH_BASHOPT))
|| (setflag && (o&SH_COMMANDLINE)))
{ {
errormsg(SH_DICT,2, e_option, opt_info.arg); errormsg(SH_DICT,2, e_option, opt_info.arg);
error_info.errors++; 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) if(sh_isoption(SH_RESTRICTED) && !f && o==SH_RESTRICTED)
errormsg(SH_DICT,ERROR_exit(1), e_restricted, opt_info.arg); errormsg(SH_DICT,ERROR_exit(1), e_restricted, opt_info.arg);
break; 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 */ case -6: /* --default */
{ {
register const Shtable_t *tp; 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)) (shp->gd->userid==shp->gd->euserid && shp->gd->groupid==shp->gd->egroupid))
off_option(&newflags,SH_PRIVILEGED); 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; shp->options = newflags;
} }
@ -647,23 +554,11 @@ void sh_printopts(Shopt_t oflags,register int mode, Shopt_t *mask)
on_option(&oflags,SH_VIRAW); on_option(&oflags,SH_VIRAW);
#endif #endif
if(!(mode&(PRINT_ALL|PRINT_VERBOSE))) /* only print set options */ 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++) for(tp=shtab_options; value=tp->sh_number; tp++)
{ {
if(mask && !is_option(mask,value&0xff)) if(mask && !is_option(mask,value&0xff))
continue; 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); on = !!is_option(&oflags,value);
name = tp->sh_name; name = tp->sh_name;
if(name[0] == 'n' && name[1] == 'o' && name[2] != 't') 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'); sfputr(sfstdout,on ? sh_translate(e_on) : sh_translate(e_off),'\n');
} }
else if(mode&PRINT_ALL) /* print unset options also */ else if(mode&PRINT_ALL) /* print unset options also */
{ sfprintf(sfstdout, "set %co %s\n", on?'-':'+', name);
if(mode&PRINT_SHOPT)
sfprintf(sfstdout, "shopt -%c %s\n",
on?'s':'u',
name);
else
sfprintf(sfstdout, "set %co %s\n",
on?'-':'+',
name);
}
else if(!(value&SH_COMMANDLINE) && is_option(&oflags,value&0xff)) 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))) if(!(mode&(PRINT_VERBOSE|PRINT_ALL)))
sfputc(sfstdout,'\n'); sfputc(sfstdout,'\n');

View file

@ -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 <dgk@research.att.com> *
* *
***********************************************************************/
/*
* bash specific extensions
* originally provided by Karsten Fleischer
*/
#include "defs.h"
#include "path.h"
#include "io.h"
#include "builtins.h"
#include "name.h"
#ifndef BASH_MAJOR
# define BASH_MAJOR "1"
# define BASH_MINOR "0"
# define BASH_PATCH "0"
# define BASH_BUILD "0"
# define BASH_RELEASE "experimental"
#endif
#define BASH_VERSION BASH_MAJOR "." BASH_MINOR "." BASH_PATCH "(" BASH_BUILD ")-" BASH_RELEASE
extern const char bash_pre_rc[];
static char *login_files[4];
const char sh_bash1[] =
"[B?Enable brace group expansion. This option is only 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 <K.Fleischer@omnium.de>]"
USAGE_LICENSE
"[+NAME?shopt - set/unset variables controlling optional shell behavior]"
"[+DESCRIPTION?\bshopt\b sets or unsets variables controlling optional shell "
"behavior. With no options, or with the \b-p\b option, a list of all "
"settable options is displayed, with an indication of whether or not "
"each is set.]"
"[p?Causes output to be displayed in a form that may be reused as input.]"
"[s?Set each \aoptname\a.]"
"[u?Unset each \aoptname\a.]"
"[q?Suppress output (quiet mode). The return status indicates whether the "
"\aoptname\a is set or unset. If multiple \aoptname\a arguments are "
"given with \b-q\b, the return status is zero if all \aoptname\as are "
"enabled; non-zero otherwise.]"
"[o?Restricts the values of \aoptname\a to be those defined for the \b-o\b "
"option to the set builtin.]"
"[+?If either \b-s\b or \b-u\b is used with no \aoptname\a arguments, the "
"display is limited to those options which are set or unset.]"
"[+?\bshopt\b supports all bash options. Some settings do not have any effect "
"or are are always on and cannot be changed.]"
"[+?The value of \aoptname\a must be one of the following:]{"
"[+cdable_vars?If set, arguments to the \bcd\b command are "
"assumed to be names of variables whose values are to "
"be used if the usual \bcd\b proceeding fails.]"
"[+cdspell?Currently ignored.]"
"[+checkhash?Always on.]"
"[+checkwinsize?Currently ignored.]"
"[+cmdhist?Always on.]"
"[+dotglob?If set, include filenames beginning with a \b.\b "
"in the results of pathname expansion.]"
"[+execfail?Always on.]"
"[+expand_aliases?Always on.]"
"[+extglob?Enable extended pattern matching features.]"
"[+histappend?Always on.]"
"[+histreedit?If set and an edit mode is selected, the user "
"is given the opportunity to re-edit a failed history "
"substitution.]"
"[+histverify?If set and an edit mode is selected, the result "
"of a history substitution will not be executed "
"immediately but be placed in the edit buffer for "
"further modifications.]"
"[+hostcomplete?Currently ignored.]"
"[+huponexit?Currently ignored.]"
"[+interactive_comments?Always on.]"
"[+lithist?Always on.]"
"[+login_shell?This option is set if the shell is started as "
"a login shell. The value cannot be changed.]"
"[+mailwarn?Currently ignored.]"
"[+no_empty_cmd_completion?Always on.]"
"[+nocaseglob?Match filenames in a case-insensitive fashion "
"when performing filename expansion.]"
"[+nullglob?Allows filename patterns which match no files to "
"expand to a null string, rather than themselves.]"
"[+progcomp?Currently ignored.]"
"[+promptvars?Currently ignored.]"
"[+restricted_shell?This option is set if the shell is started "
"as a restricted shell. The value cannot be changed. "
"It is not reset during execution of startup files, "
"allowing the startup files to determine whether the "
"shell is restricted.]"
"[+shift_verbose?Currently ignored.]"
"[+sourcepath?If set, the \b.\b builtin uses the value of PATH "
"to find the directory containing the file supplied "
"as an argument.]"
"[+xpg_echo?If set, the \becho\b and \bprint\b builtins "
"expand backslash-escape sequences.]"
"}"
"\n"
"\n[optname ...]\n"
"\n"
"[+EXIT STATUS?]{"
"[+?The return status when listing options is zero if all \aoptnames\a "
"are enabled, non-zero otherwise. When setting or unsetting options, "
"the return status is zero unless an \aoptname\a is not a valid shell "
"option.]"
"}"
"[+SEE ALSO?\bset\b(1)]"
;
/* GLOBIGNORE discipline. Turn on SH_DOTGLOB on set, turn off on unset. */
static void put_globignore(register Namval_t* np, const char *val, int flags, Namfun_t *fp)
{
if(val)
sh_onoption(SH_DOTGLOB);
else
sh_offoption(SH_DOTGLOB);
nv_putv(np,val,flags,fp);
}
const Namdisc_t SH_GLOBIGNORE_disc = { sizeof(Namfun_t), put_globignore };
/* FUNCNAME discipline */
struct funcname
{
Namfun_t hdr;
};
static void put_funcname(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
{
/* bash silently returns with an error when FUNCNAME is set,
unsetting FUNCNAME is allowed */
if(val && !(flags&NV_RDONLY))
error_info.exit(1);
nv_putv(np,val,flags,fp);
}
const Namdisc_t SH_FUNCNAME_disc = { sizeof(struct funcname), put_funcname };
#define SET_SET 1
#define SET_UNSET 2
#define SET_NOARGS 4
/* shopt builtin */
int b_shopt(int argc,register char *argv[],void *extra)
{
Shell_t *shp = (Shell_t*)extra;
int n, f, ret=0;
Shopt_t newflags=shp->options, opt;
int verbose=PRINT_SHOPT|PRINT_ALL|PRINT_NO_HEADER|PRINT_VERBOSE;
int setflag=0, quietflag=0, oflag=0;
memset(&opt,0,sizeof(opt));
#if SHOPT_RAWONLY
on_option(&newflags,SH_VIRAW);
#endif
while((n = optget(argv,sh_optshopt)))
{
switch(n)
{
case 'p':
verbose&=~PRINT_VERBOSE;
break;
case 's':
case 'u':
setflag|=n=='s'?SET_SET:SET_UNSET;
if(setflag==(SET_SET|SET_UNSET))
{
errormsg(SH_DICT,ERROR_ERROR,"cannot set and unset options simultaneously");
error_info.errors++;
}
break;
case 'q':
quietflag=1;
break;
case 'o':
oflag=1;
verbose&=~PRINT_SHOPT;
break;
case ':':
errormsg(SH_DICT,2, "%s", opt_info.arg);
continue;
case '?':
errormsg(SH_DICT,ERROR_usage(0), "%s", opt_info.arg);
return(-1);
}
}
if(error_info.errors)
errormsg(SH_DICT,ERROR_usage(2),"%s",optusage(NIL(char*)));
argc -= opt_info.index;
if(argc==0)
{
/* no args, -s => mask=current options, -u mask=~(current options)
else mask=all bits */
if(setflag&SET_SET)
opt=newflags;
else if(setflag&SET_UNSET)
for(n=0;n<4;n++)
opt.v[n]=~newflags.v[n];
else
memset(&opt,0xff,sizeof(opt));
setflag=SET_NOARGS;
}
while(argc>0)
{
f=1;
n=sh_lookopt(argv[opt_info.index],&f);
if(n<=0||(setflag
&& (is_option(&opt,SH_INTERACTIVE)
|| is_option(&opt,SH_RESTRICTED)
|| is_option(&opt,SH_RESTRICTED2)
|| is_option(&opt,SH_BASH)
|| is_option(&opt,SH_LOGIN_SHELL)))
||(oflag&&(n&SH_BASHOPT)))
{
errormsg(SH_DICT,ERROR_ERROR, e_option, argv[opt_info.index]);
error_info.errors++;
ret=1;
}
else if(f)
on_option(&opt,n&0xff);
else
off_option(&opt,n&0xff);
opt_info.index++;
argc--;
}
if(setflag&(SET_SET|SET_UNSET))
{
if(setflag&SET_SET)
{
if(sh_isoption(SH_INTERACTIVE))
off_option(&opt,SH_NOEXEC);
if(is_option(&opt,SH_VI)||is_option(&opt,SH_EMACS)||is_option(&opt,SH_GMACS))
{
off_option(&newflags,SH_VI);
off_option(&newflags,SH_EMACS);
off_option(&newflags,SH_GMACS);
}
for(n=0;n<4;n++)
newflags.v[n] |= opt.v[n];
}
else if(setflag&SET_UNSET)
for(n=0;n<4;n++)
newflags.v[n] &= ~opt.v[n];
sh_applyopts(shp,newflags);
shp->options = newflags;
if(is_option(&newflags,SH_XTRACE))
sh_trace(shp,argv,1);
}
else if(!(setflag&SET_NOARGS)) /* no -s,-u but args, ret=0 if opt&mask==mask */
{
for(n=0;n<4;n++)
ret+=((newflags.v[n]&opt.v[n])!=opt.v[n]);
}
if(!quietflag&&!(setflag&(SET_SET|SET_UNSET)))
sh_printopts(newflags,verbose,&opt);
return(ret);
}
/* mode = 0: init, called two times
before parsing shell args with SH_PREINIT state turned on
second time after sh_init() is through and with SH_PREINIT state turned off
mode > 1: re-init
mode < 0: shutdown
*/
void bash_init(Shell_t *shp,int mode)
{
Sfio_t *iop;
Namval_t *np;
int n=0,xtrace,verbose;
if(mode>0)
goto reinit;
if(mode < 0)
{
/* termination code */
if(sh_isoption(SH_LOGIN_SHELL) && !sh_isoption(SH_POSIX))
sh_source(shp, NiL, sh_mactry(shp,(char*)e_bash_logout));
return;
}
if(sh_isstate(SH_PREINIT))
{ /* pre-init stage */
if(sh_isoption(SH_RESTRICTED))
sh_onoption(SH_RESTRICTED2);
sh_onoption(SH_HISTORY2);
sh_onoption(SH_INTERACTIVE_COMM);
sh_onoption(SH_SOURCEPATH);
sh_onoption(SH_HISTAPPEND);
sh_onoption(SH_CMDHIST);
sh_onoption(SH_LITHIST);
sh_onoption(SH_NOEMPTYCMDCOMPL);
if(shp->login_sh==2)
sh_onoption(SH_LOGIN_SHELL);
if(strcmp(astconf("CONFORMANCE",0,0),"standard")==0)
sh_onoption(SH_POSIX);
if(strcmp(astconf("UNIVERSE",0,0),"att")==0)
sh_onoption(SH_XPG_ECHO);
else
sh_offoption(SH_XPG_ECHO);
if(strcmp(astconf("PATH_RESOLVE",0,0),"physical")==0)
sh_onoption(SH_PHYSICAL);
else
sh_offoption(SH_PHYSICAL);
/* add builtins */
sh_addbuiltin("shopt", b_shopt, &sh);
/* set up some variables needed for --version
* needs to go here because --version option is parsed before the init script.
*/
if(np=nv_open("HOSTTYPE",shp->var_tree,0))
nv_putval(np, BASH_HOSTTYPE, NV_NOFREE);
if(np=nv_open("MACHTYPE",shp->var_tree,0))
nv_putval(np, BASH_MACHTYPE, NV_NOFREE);
if(np=nv_open("BASH_VERSION",shp->var_tree,0))
nv_putval(np, BASH_VERSION, NV_NOFREE);
if(np=nv_open("BASH_VERSINFO",shp->var_tree,0))
{
char *argv[7];
argv[0] = BASH_MAJOR;
argv[1] = BASH_MINOR;
argv[2] = BASH_PATCH;
argv[3] = BASH_BUILD;
argv[4] = BASH_RELEASE;
argv[5] = BASH_MACHTYPE;
argv[6] = 0;
nv_setvec(np, 0, 6, argv);
nv_onattr(np,NV_RDONLY);
}
return;
}
/* rest of init stage */
/* restrict BASH_ENV */
if(np=nv_open("BASH_ENV",shp->var_tree,0))
{
const Namdisc_t *dp = nv_discfun(NV_DCRESTRICT);
Namfun_t *fp = calloc(dp->dsize,1);
fp->disc = dp;
nv_disc(np, fp, 0);
}
/* open GLOBIGNORE node */
if(np=nv_open("GLOBIGNORE",shp->var_tree,0))
{
const Namdisc_t *dp = &SH_GLOBIGNORE_disc;
Namfun_t *fp = calloc(dp->dsize,1);
fp->disc = dp;
nv_disc(np, fp, 0);
}
/* set startup files */
n=0;
if(sh_isoption(SH_LOGIN_SHELL))
{
if(!sh_isoption(SH_POSIX))
{
login_files[n++] = (char*)e_bash_profile;
login_files[n++] = (char*)e_bash_login;
}
login_files[n++] = (char*)e_profile;
}
shp->login_files = login_files;
reinit:
xtrace = sh_isoption(SH_XTRACE);
sh_offoption(SH_XTRACE);
verbose = sh_isoption(SH_VERBOSE);
sh_offoption(SH_VERBOSE);
if(np = nv_open("SHELLOPTS", shp->var_tree, NV_NOADD))
nv_offattr(np,NV_RDONLY);
iop = sfopen(NULL, bash_pre_rc, "s");
sh_eval(iop,0);
if(xtrace)
sh_offoption(SH_XTRACE);
if(verbose)
sh_offoption(SH_VERBOSE);
}

View file

@ -96,10 +96,6 @@ int path_expand(Shell_t *shp,const char *pattern, struct argnod **arghead)
register struct argnod *ap; register struct argnod *ap;
register glob_t *gp= &gdata; register glob_t *gp= &gdata;
register int flags,extra=0; register int flags,extra=0;
#if SHOPT_BASH
register int off;
register char *sp, *cp, *cp2;
#endif
sh_stats(STAT_GLOBS); sh_stats(STAT_GLOBS);
memset(gp,0,sizeof(gdata)); memset(gp,0,sizeof(gdata));
flags = GLOB_GROUP|GLOB_AUGMENTED|GLOB_NOCHECK|GLOB_NOSORT|GLOB_STACK|GLOB_LIST|GLOB_DISC; 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; flags |= GLOB_MARK;
if(sh_isoption(SH_GLOBSTARS)) if(sh_isoption(SH_GLOBSTARS))
flags |= GLOB_STARSTAR; 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(sh_isstate(SH_COMPLETE))
{ {
#if KSHELL #if KSHELL
@ -129,62 +115,6 @@ int path_expand(Shell_t *shp,const char *pattern, struct argnod **arghead)
flags |= GLOB_COMPLETE; flags |= GLOB_COMPLETE;
flags &= ~GLOB_NOCHECK; 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)); gp->gl_fignore = nv_getval(sh_scoped(shp,FIGNORENOD));
if(suflen) if(suflen)
gp->gl_suffix = sufstr; 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) if(memcmp(pattern,"~(N",3)==0)
flags &= ~GLOB_NOCHECK; flags &= ~GLOB_NOCHECK;
glob(pattern, flags, 0, gp); glob(pattern, flags, 0, gp);
#if SHOPT_BASH
if(off)
stakset(sp,off);
else
stakseek(0);
#endif
sh_sigcheck(shp); sh_sigcheck(shp);
for(ap= (struct argnod*)gp->gl_list; ap; ap = ap->argnxt.ap) for(ap= (struct argnod*)gp->gl_list; ap; ap = ap->argnxt.ap)
{ {

View file

@ -87,10 +87,6 @@ char e_version[] = "\n@(#)$Id: Version "
#define ATTRS 1 #define ATTRS 1
"A" "A"
#endif #endif
#if SHOPT_BASH
#define ATTRS 1
"B"
#endif
#if SHOPT_BGX #if SHOPT_BGX
#define ATTRS 1 #define ATTRS 1
"J" "J"
@ -116,10 +112,6 @@ char e_version[] = "\n@(#)$Id: Version "
#endif #endif
SH_RELEASE " $\0\n"; SH_RELEASE " $\0\n";
#if SHOPT_BASH
extern void bash_init(Shell_t*,int);
#endif
#define RANDMASK 0x7fff #define RANDMASK 0x7fff
#ifndef ARG_MAX #ifndef ARG_MAX
@ -1103,7 +1095,7 @@ int sh_type(register const char *path)
} }
for (;;) for (;;)
{ {
if (!(t & (SH_TYPE_KSH|SH_TYPE_BASH))) if (!(t & SH_TYPE_KSH))
{ {
if (*s == 'k') if (*s == 'k')
{ {
@ -1111,14 +1103,6 @@ int sh_type(register const char *path)
t |= SH_TYPE_KSH; t |= SH_TYPE_KSH;
continue; continue;
} }
#if SHOPT_BASH
if (*s == 'b' && *(s+1) == 'a')
{
s += 2;
t |= SH_TYPE_BASH;
continue;
}
#endif
} }
if (!(t & (SH_TYPE_PROFILE|SH_TYPE_RESTRICTED))) if (!(t & (SH_TYPE_PROFILE|SH_TYPE_RESTRICTED)))
{ {
@ -1143,6 +1127,8 @@ int sh_type(register const char *path)
{ {
s++; s++;
t |= SH_TYPE_SH; t |= SH_TYPE_SH;
if (!(t & SH_TYPE_KSH))
t |= SH_TYPE_POSIX;
if ((t & SH_TYPE_KSH) && *s == '9' && *(s+1) == '3') if ((t & SH_TYPE_KSH) && *s == '9' && *(s+1) == '3')
s += 2; s += 2;
#if _WINIX #if _WINIX
@ -1152,7 +1138,7 @@ int sh_type(register const char *path)
if (!isalnum(*s)) if (!isalnum(*s))
return t; 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); type = sh_type(*argv);
if(type&SH_TYPE_LOGIN) if(type&SH_TYPE_LOGIN)
shp->login_sh = 2; shp->login_sh = 2;
if(type&SH_TYPE_POSIX || strcmp(astconf("CONFORMANCE",0,0),"standard")==0)
sh_onoption(SH_POSIX);
} }
env_init(shp); env_init(shp);
if(!ENVNOD->nvalue.cp) 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 */ /* check for profile shell */
else if(type&SH_TYPE_PROFILE) else if(type&SH_TYPE_PROFILE)
sh_onoption(SH_PFSH); 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 #endif
/* look for options */ /* look for options */
/* shp->st.dolc is $# */ /* shp->st.dolc is $# */

View file

@ -576,13 +576,9 @@ int sh_lex(Lex_t* lp)
return(lp->token=c); return(lp->token=c);
else if(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) /* bash-style "&>file" shorthand for ">file 2>&1" */
{
lp->nonstandard = 1;
errormsg(SH_DICT,ERROR_warn(0),e_lexnonstandard,shp->inlineno);
}
lp->digits = -1; lp->digits = -1;
c = '>'; c = '>';
} }

View file

@ -163,7 +163,6 @@ int sh_main(int ac, char *av[], Shinit_f userinit)
if((beenhere++)==0) if((beenhere++)==0)
{ {
sh_onstate(SH_PROFILE); sh_onstate(SH_PROFILE);
((Lex_t*)shp->lex_context)->nonstandard = 0;
if(shp->gd->ppid==1) if(shp->gd->ppid==1)
shp->login_sh++; shp->login_sh++;
if(shp->login_sh >= 2) 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_BGNICE);
sh_onoption(SH_RC); sh_onoption(SH_RC);
} }
if(!sh_isoption(SH_RC) && (sh_isoption(SH_BASH) && !sh_isoption(SH_POSIX)
#if SHOPT_REMOTE #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); sh_onoption(SH_RC);
#endif
for(i=0; i<elementsof(shp->offoptions.v); i++) for(i=0; i<elementsof(shp->offoptions.v); i++)
shp->options.v[i] &= ~shp->offoptions.v[i]; shp->options.v[i] &= ~shp->offoptions.v[i];
if(sh_isoption(SH_INTERACTIVE)) if(sh_isoption(SH_INTERACTIVE))
@ -212,17 +213,6 @@ int sh_main(int ac, char *av[], Shinit_f userinit)
{ {
if(!sh_isoption(SH_NOUSRPROFILE) && !sh_isoption(SH_PRIVILEGED) && sh_isoption(SH_RC)) if(!sh_isoption(SH_NOUSRPROFILE) && !sh_isoption(SH_PRIVILEGED) && sh_isoption(SH_RC))
{ {
#if SHOPT_BASH
if(sh_isoption(SH_BASH) && !sh_isoption(SH_POSIX))
{
#if SHOPT_SYSRC
sh_source(shp, iop, e_bash_sysrc);
#endif
sh_source(shp, iop, shp->gd->rcfile ? shp->gd->rcfile : sh_mactry(shp,(char*)e_bash_rc));
}
else
#endif
{
if(name = sh_mactry(shp,nv_getval(ENVNOD))) if(name = sh_mactry(shp,nv_getval(ENVNOD)))
name = *name ? strdup(name) : (char*)0; name = *name ? strdup(name) : (char*)0;
#if SHOPT_SYSRC #if SHOPT_SYSRC
@ -235,7 +225,6 @@ int sh_main(int ac, char *av[], Shinit_f userinit)
free(name); free(name);
} }
} }
}
else if(sh_isoption(SH_INTERACTIVE) && sh_isoption(SH_PRIVILEGED)) else if(sh_isoption(SH_INTERACTIVE) && sh_isoption(SH_PRIVILEGED))
sh_source(shp, iop, e_suidprofile); sh_source(shp, iop, e_suidprofile);
} }

View file

@ -549,7 +549,7 @@ void nv_setlist(register struct argnod *arg,register int flags, Namval_t *typ)
{ {
if(!(arg->argflag&ARG_APPEND)) if(!(arg->argflag&ARG_APPEND))
_nv_unset(np,NV_EXPORT); _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); nv_setarray(np,nv_associative);
} }
skip: skip:

View file

@ -1086,19 +1086,6 @@ int sh_exec(register const Shnode_t *t, int flags)
} }
if(np) if(np)
flgs |= NV_UNJUST; 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) if(np && np->nvalue.bfp==SYSTYPESET->nvalue.bfp)
{ {
/* command calls b_typeset(); treat as a typeset variant */ /* 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 */ #endif /* SHOPT_TYPEDEF */
if((shp->fn_depth && !shp->prefix) || np==SYSLOCAL) if((shp->fn_depth && !shp->prefix))
flgs |= NV_NOSCOPE; flgs |= NV_NOSCOPE;
} }
else if(np==SYSEXPORT) else if(np==SYSEXPORT)

View file

@ -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" else err_exit "mkfifo failed; cannot test reading from FIFO"
fi 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)) exit $((Errors<125?Errors:125))

View file

@ -53,28 +53,9 @@ then err_exit 'sh -e not working'
fi fi
[[ $($SHELL -D -c 'print hi; print $"hello"') == '"hello"' ]] || err_exit 'ksh -D not working' [[ $($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 rc=$tmp/.kshrc
print $'PS1=""\nfunction env_hit\n{\n\tprint OK\n}' > $rc 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 export ENV=/.$rc
if [[ -o privileged ]] if [[ -o privileged ]]
then then