#!/bin/ksh \: # shadoe - debugger for k/sh scripts #*TAG:58910 81:Apr 17 1997:0755:sh.d/shadoe:shadoe: # @(#)shadoe.sh 1.0A 1997/03 bsh29256@atc.fhda.edu (Brian S. Hiles) # shadoe - "SHell And Debugger Observing Environment" # display and/or modify the environment in a running shell prog # Author: bsh20858@atc.fhda.edu (Brian S. Hiles) # Copyright: (c) 1996, 1997. All rights reserved for this ALPHA version # Usage: shadoe [shadoe-options...] -- shprog [shprog-options...] # # A component of my SHell Integrated Development Environment ("shide") project. # Advisor: instructor Roberta Harvey of Foothill Coll., Los Altos Hills, CA. # example: shadoe -ox shprog [opts] # Track all changed variables and their attributes, showing old values # when they change. Shprog commands are displayed as they are executed. # # example: shadoe -e -t var1,var2 shprog [opts] # Track variables var1 and var2 and their attributes, displaying # any changed environment on an error. # # example: shadoe -aaev -g 100 -r 2+_qlnnodisp,120 shprog [opts] # On the occurrence of any error from the second line to the 20th # line of script "shprog ", show the complete environment if # it has changed. Commands are displayed to stderr as they are read. # # The above options may be placed into variable SHADOERC or file # .shadoerc for automatic inclusion into each "shadoe" command line. # Also, optional files shadoe.pre, shadoe.trans, and shadoe.post will # be sourced before, at each trap, and at termination of the shprog. # # Shadoe will display the current environment with the program spec- # ified with the variable VISUAL, or if that is unset or null, var- # iable EDITOR, or if that is unset or null, variable PAGER, else # "pg". To modify the environment dynamically, edit the displayed # environment file if using an editor, or if using a pager use the # shell escape mechanism to edit either file "~/.env" or # file "~/.denv". The changes will be automatic in the run- # ning shell program when returning. A trap on ERR will only display # upon a changed environment; set _qcontrol<0 to force a display. # # Shadoe purposely doesn't track variables, aliases, and functions # with names beginning with "_q", and the special variables LINENO, # PS4, RANDOM, SECONDS, and (unless option -u is specified) _, due # to the fact that their values would necessarily change from line # to line. Shadoe (may) subsume variable PS4, the tagged attribute # on variables, aliases for "exit" and "limit", the traced and # autoloaded attributes on functions, and the DEBUG and/or ERR trap. # # One "-a" option is made default, as shadoe runs a "quick and # dirty" variable trace without any. For additional caveats, # search on the strings "Diagnostic", "Ksh Bug", and "Warning". # Try running shadoe on itself to discern more of its internals. #01 FILES # # significant if present: # .shadoerc - optional file of default command line options(*) # shadoe.pre - optional file of code to source before execution(*) # shadoe.trans - optional file of code to source on each trap # shadoe.post - optional file of code to source after execution(*) # (*) sourced/read in the environment of the debugger, not the shprog. # # created in directory $TMPDIR/_q$$.d: # _qcenv - current environment state after current execution # ~/.env - file alias of the above # _qe2disp.sed - sed script to create env display # _qdenv - holds difference between old and current environment # ~/.denv - file alias of the above # _qoenv - old environment state from last execution # _qshadoe - autoloaded debugger function # _qstatus - file holding termination status prompt of shprog # _qtmp # # files left after termination: # .env - file copy of last env # shadoe.out - file of all stderr output of shprog and debugger # shadoe.sa - standalone version of munged shprog (-z option) #02 USAGE REPORT # default options are: -ad -g0 -r1, (and, only for ksh88: -k) _USAGE=\ 'shadoe [-d|-e] [-acikmouvwxz] [-fpt ] [-glnr ] shprog [opts] -a - print out addition information, not just variable values(*) -c - execute shprog within a cleared environment -d - display the environment when it changes (default) -e - display the environment only when an error occurs -f fn[,...] - apply -x option to comma-separated list of function names(*) -g expr - globally offset LINENO by in shprog (default: 0) -i - attempt to ignore trap 0 (EXIT) in shprog -k - if exists, source the per-process ENV script (default) -l expr[,...] - set debug trap at comma-separated list of line numbers(*) -m - "manual" mode: script itself expected to invoke debugging -n expr[,...] - like -l option, except force display of environment(*) -o - show old values of reassigned variables/aliases/traps also -p file - use file as previous environment display -r expr[,expr] - specify range of lines to begin [and end] debugging -s shell - force the use of shell (default: $SHELL) -t var[,...] - track only vars specified by the comma-separated list(*) -u - track variable underscore ("_") also (default: ignored) -v - print shell input lines as they are read -w - source shadoe.trans when at trap (default: only when diff env) -x - print commands as they are executed -z - at termination, create standalone shprog version "shadoe.sa" -? - show this usage report (*) option may be specified multiple times to increase scope of option.' #03 LOAD RC OPTIONS # introduce one '-a' option; it may be overruled by an explicit '+a' option. # if desiring to suppress initializing from .shadoerc, set SHADOERC=' '. if [[ -n $SHADOERC ]] then \set -- -a $SHADOERC "$@" elif [[ -f .shadoerc && -r .shadoerc ]] then \set -- -a $(<.shadoerc) "$@" elif [[ -f ~/.shadoerc && -r ~/.shadoerc ]] then \set -- -a $(<~/.shadoerc) "$@" else \set -- -a "$@" fi #04 PARSE OPTIONS # Warning: in ksh93: change ":ab..." below to ":+ab..." for ksh88 compatibility while getopts :abcdf:g:ikl:mn:op:r:s:t:uvxz _inst do case $_inst in (a) _addout="$_addout,ON" ;; (+a) _addout=${_addout#,ON} ;; (c) _clearenv=ON ;; (+c) _clearenv= ;; (d) _debugtrap=ON _errtrap= ;; # mutually exclusive with -e (+d) _debugtrap= _errtrap=ON ;; (e) _debugtrap= _errtrap=ON ;; # mutually exclusive with -d (+e) _debugtrap=ON _errtrap= ;; (f) # specify option parameter "_qALL" to trace all functs. # option parameter "_qmain" is equivalent to -x option. _fntrace="$_fntrace,$OPTARG" ;; (g) _qlnnodisp=$OPTARG ;; (i) _ignexit=ON ;; (+i) _ignexit= ;; (k) # Warning: ksh93 sources $ENV file only when interactive _source_ENV_script=ON ;; (+k) _source_ENV_script= ;; (l) _lnnotrap=$_lnnotrap,$OPTARG ;; (m) _autostart= ;; (+m) _autostart=ON ;; (o) _showovalues=ON ;; (+o) _showovalues= ;; (p) # must conform to the internal format of an env file _oenv=$OPTARG ;; (r) if [[ $OPTARG = *,* ]] then [[ $OPTARG = *?,* ]] && _qbgnlnno=${OPTARG%%,*} [[ $OPTARG = *,?* ]] && _qendlnno=${OPTARG#*,} else _qbgnlnno=$OPTARG _qendlnno=$OPTARG fi ;; (s) # shell option(s) may be included within the option arg _qshell=$OPTARG ;; (t) _tagvars=$_tagvars,$OPTARG ;; (u) _uscore=ON ;; (+u) _uscore= ;; (v) _verbose=ON ;; (+v) _verbose= ;; (w) _whenenv= _whentrap=ON ;; (+w) _whenenv=ON _whentrap= ;; (x) _xtrace=ON ;; (+x) _xtrace= ;; (z) _dumpsrc=ON ;; (+z) _dumpsrc= ;; (:|\?|+\?) print -ru2 -- "$_USAGE" \exit 2 ;; esac done \shift OPTIND-1 PAGER= EDITOR= VISUAL= #XXX you will want to delete this eventually! #05 DEFAULTS AND CHECKS # Warning: all "_q*" variables should have no embedded newlines. # Ksh Bug: rbrace in variable substitution is impossible, even if escaped. _version='#. SHADOE 0.99B, ${_qshell##*/} $_src, %D, %H:%M' \ _RB=\} _TAB=' ' _showcode=$_verbose$_xtrace \eval _kshpath=$(whence -p $SHELL) \: ${_qdir:=${TMPDIR:-/tmp}/_q$$.d/} ${_autostart=ON} \ ${_debugtrap=ON} ${_profile[0]:=shadoe.pre} ${_profile[1]:=shadoe.trans} \ ${_profile[2]:=shadoe.post} ${_kshpath:=/bin/ksh} ${_whenenv=ON} \ ${_qprompt=$(tput -T$TERM smso)[\$1] ${0##*/}\>$(tput -T$TERM rmso) } # advanced configuration flags: To assert, set to ON; to unassert, set to null # example: dont_use_profiles=ON print_funct_names=ON shadoe -aa shprog opts \: ${cvt_signames_nums=} # convert signal symbolic names to num equiv? \: ${dont_use_profiles=} # do not use any pre/trans/post-profile files? \: ${env_newlines=ON} # display with _!NL!_s restored to newlines? \: ${ignore_uscore_vars=} # ignore vars/aliases/functs with leading "_"? \: ${print_funct_names=} # print all function names found in shprog? \: ${skip_initial_env=} # skip display of env inherited from parent? \: ${trapno_cutoff=32} # don't cvt trap names to nums >= this value. # Diagnostic 'sed: too many commands': set 0 if [[ -n $1 ]] then _src=$1 \shift if [[ $_src = /* ]] then _src=/$_src elif [[ $_src != */* ]] then _src=./$_src fi \cd -- ${_src%/*} || \exit 1 _src=${PWD%/}/${_src##*/} \cd - >&- [[ -f $_src && -r $_src && -s $_src ]] || { print -ru2 "shadoe: error: \"$_src\" not a file," \ 'nonexistent, empty, or not readable' \exit 1 } else print -ru2 -- "$_USAGE" \exit 2 fi ${VERBOSE:+print -ru2 [ source file: $_src ]} # Warning: set appropriate umask for security [[ -d $_qdir ]] || /bin/mkdir -p $_qdir || \exit 3 \cd -- $_qdir || \exit 4 if [[ -n $_oenv ]] then /bin/sed -n p $_oenv >|./_qoenv else \: >|./_qoenv fi ${VERBOSE:+print -ru2 [ environment file: ${_oenv:-$PWD/_qoenv} ]} # determine if appropriate quoting implemented in "typeset -" output. # Warning: if not implemented, need to _guess_ at var/value delimitation! # Ksh Bug: i86 Solaris 2.x ksh[88i] fails in this respect. \eval $(_inst=' ' \typeset - | /bin/sed -n \ '/^_inst=$/q; s/.*/_quotedenv=ON/p; q') # Diagnostic "different file systems": set variable TMPDIR # to appropriate directory of same filesystem as your cwd. if /bin/rm -f ./_qtmp /bin/ln -s /dev/null ./_qtmp then _symlinkok=ON /bin/rm -f ./_qtmp else _symlinkok= fi 2>&- for _inst in _addout _fntrace _tagvars { # strip extraneous left and right comma delimiters \eval $_inst=\$\{$_inst##+(,)\} $_inst=\$\{$_inst%%+(,)\} } IFS=" ,$IFS" [[ -n $_addout ]] && \set -A _addout ${_addout[*]} [[ -n $_tagvars ]] && { [[ ,$_tagvars, = *,_,* ]] && _uscore=ON \set -A _tagvars -- $_tagvars ${VERBOSE:+print -ru2 [ tracing variables: ${_tagvars[*]} ]} } # Warning: if no -a option is specified, shadoe can only reliably function # in ksh88 if no displayed variables in the shprog are multi-line. [[ -n ${_addout[1]} || -n $cvt_signames_nums ]] && { (($trapno_cutoff>0)) && [[ -n ${_addout[1]} ]] && { # generate sed code to convert trap names to numbers _names2nums="$( print 't treset4\n: treset4' # Warning: ksh88 has arcane output format for "kill -l" # so /bin/kill command is used instead to list signals. \typeset -i _trapno=-1 idx for _inst in EXIT $(/bin/kill -l) { [[ $_inst = *[!0-9A-Z]* ]] && break (((_trapno+=1)>$trapno_cutoff)) && break { print -r "s/ $_inst$/ $_trapno/" \let idx+=1 idx%2 || print -r 't SH' } } print -r 't SH' )" } } [[ ,$_fntrace, = *,_qmain,* ]] && _xtrace=ON # trace "_qmain" :=: option -x [[ ,$_fntrace, = ,+(_qmain,) ]] && _fntrace= # _qmain only "funct" to trace [[ -n $_fntrace ]] && { # technique used to trace functions will differ depending on options. if [[ ,$_fntrace, = *,_qALL,* ]] then _addout[0]=ON _addout[1]=ON _fncode='s/-fu /-ftu /' _fntrace= else if [[ -n ${_addout[1]} ]] then # You have already specified functions to be displayed, # so use sed technique to trace (autoloaded) functions. _fncode=$( IFS=, for _inst in $_fntrace { print -r "/${_inst}_EOF/s/-fu /-ftu /" } ) _fntrace= ${VERBOSE:+print -ru2 [ tracing functions: using _fncode=$_fncode technique ]} else # using 'typeset -ftu ...' technique _fncode= \set -A _fntrace -- $_fntrace ${VERBOSE:+print -ru2 [ tracing functions: using typeset -ftu ... technique ]} fi fi } #06 WHICH SHELL? if _line1=$(/bin/sed 1q $_src) [[ $_line1 = \#!* ]] then \: ${_qshell:=$_line1} # won't redefine if previously set by -s option _qshell=${_qshell##\#!*([$_TAB ])} fi \: ${_qshell:=$_kshpath $-} [[ $_qshell = *+([$_TAB ])-* ]] && _qshopts=${_qshell##*+([$_TAB ])-} _qshell=${_qshell%%+([$_TAB ])*} _qshell=${_qshell%%[$_TAB ]*} _qshell=$( whence -p $_qshell 2>&- || { print -ru2 "shadoe: error: shell \"$_qshell\" not in path" \exit 1 } ) || \exit 5 ${VERBOSE:+print -ru2 [ shell: _qshell=\"$_qshell\" _qshopts=\"$_qshopts\" ]} # Warning: ksh command line options [cirs] are inappropriate as "set" options. [[ $_qshopts = *[cirs]* ]] && { print -ru2 \ "shadoe: error: shell option(s) \"$_qshopts\" unimplementable" \exit 6 } case /$_qshell in # any other shells that I don't know about? # Warning: some systems have ksh installed as "sh" (*/?(r)@(|a|j|oa)sh|*/?(r)sh5|*/?(r)bash|*/?(r)old) # sourcing ENV script has to be explicitly enabled. # converting signal names has to be explicitly disabled. _isbourne=ON _uscore= \: ${cvt_signames_nums=ON} ;; (*/?(r)@(@(dt|t)ksh|ksh93)) _isbourne= _isksh93=ON \: ${_source_ENV_script=ON} ;; (*/krsh|*/?(r)@(@(|pd|w|x)ksh|ksh-i|keysh|ksh@(86|88)|zsh)) # sourcing ENV script has to be explicitly disabled. # converting signal names has to be explicitly enabled. _isbourne= \: ${_source_ENV_script=ON} ;; (*/@(|h|j|nt|t)csh|*/es|*/rc|*/?(n|o)awk|*/?(i|n)make|*/perl|*/sed) print -ru2 "shadoe: error: cannot debug \"$_qshell\" scripts" \exit 7 ;; (*) # ch, esh, itcl_sh, ish, osh, scsh, ssh, sush, tshell, vsh ... print -ru2 "shadoe: warning: \"$_qshell\" unknown;" \ 'assuming bourne shell' _isbourne=ON _uscore= \: ${cvt_signames_nums=ON} sleep 1 ;; esac $_qshell -c ': ${.sh.version}' 2>&- && _isksh93=ON [[ -n $_isksh93 ]] && _isbourne= ${VERBOSE:+print -nru2 '[ flags: '} for _inst in _addout _fntrace _isbourne _isksh93 _quotedenv _tagvars { # if variable is unasserted, then assert variable _no \eval "[[ -z \"\$$_inst\" ]] && _no${_inst#_}=ON" ${VERBOSE:+eval print -nru2 "\"$_inst=\$$_inst \""} } ${VERBOSE:+print -ru2 ]} ${VERBOSE:+print -ru2 [ pager/editor: ${VISUAL:-${EDITOR:-${PAGER:-pg}}} ]} #07 PROFILE FILES for _inst in '0 pre' '1 trans' '2 post' { \set -A _inst $_inst \eval ${dont_use_profiles:+_profile[_inst]= continue} \eval _profile[_inst]=${_profile[_inst]} # Ksh Bug: tilde subst [[ ${_profile[_inst]} != */* ]] && if [[ -f ${_profile[_inst]} ]] then _profile[_inst]=~+/${_profile[_inst]} elif [[ -f ~/${_profile[_inst]} ]] then _profile[_inst]=~/${_profile[_inst]} fi if [[ -r ${_profile[_inst]} ]] then print -ru2 \ "using ${_inst[1]}-execution profile \"${_profile[_inst]}\"" else \unset _profile[_inst] fi } #08 SED SCRIPT [[ -n $_addout ]] && /bin/sed "1 !{ /^[$_TAB ]*#/d; }" <<-!!!! >|./_qe2disp.sed #n - turn 'shadoe' env display into the ${_noisbourne:+k}sh${_isksh93:+93} \ code to recreate that env # ksh93's new -p option for builtins _should_ have obsolesced all of the below! # reserved tokens for this script: "_!NL!_", "_!SQ!_", "_!ESCSQ!_", /^#\. /. /^#\. SHADOE /b SH : Xpre # Warning: function blocks _must_ be delimited by a rbrace on the left margin /^#\. FUNCTIONS:$/,/^#\. / { // !{ : newfunc /\\n}/b endfunc N b newfunc : endfunc #${_isbourne:+s/^function \([0-9A-Z_a-z]*\)\\n/\1 ()_!NL!_/} ${ignore_uscore_vars:+/^function _/d} s/\\n/_!NL!_/gp } b SH } # special case efficiency measure: /^_qsrcline\[/d ${_isksh93:+ # ksh93 "typeset -" already substitutes newlines as ANSI sequences: /=$'/ s/'/_!SQ!_/g } # ... for other formats, conjoin any multi-line entries into one-liners first: /'/b squote ${ignore_uscore_vars:+/^_/d} # strip all one-liners of _q* variables and aliases: /^_q/d # efficiency measure: equal sign here can only mean (one-liner) var/alias/trap: /=/b eqlsign ${_addout[2]:+ /^#\. UMASK:$/,/^#\. / { b SH $_RB } ${_addout[0]:+ /^#\. VARIABLES READONLY:$/,/^#\. / { //!s/^/${_isbourne:+readonly }${_noisbourne:+typeset -r }/ b SH $_RB /^#\. VARIABLES EXPORTED:$/,/^#\. / { //!s/^/${_isbourne:+export }${_noisbourne:+typeset -x }/ b SH $_RB ${_isksh93:+ /^#\. VARIABLES ASSOCIATIVE:$/,/^#\. / { //!s/^/typeset -A / b KSH $_RB #/^#\. VARIABLES CLASS:$/,/^#\. / { # //!s/^/typeset -C / # b KSH #$_RB /^#\. VARIABLES EXPONENT:$/,/^#\. / { //!s/^/typeset -E / b KSH $_RB /^#\. VARIABLES FLOAT:$/,/^#\. / { //!s/^/typeset -F / b KSH $_RB } ${_noisbourne:+ /^#\. VARIABLES FILENAME:$/,/^#\. / { //!s/^/typeset -H / b KSH $_RB /^#\. VARIABLES LEFTJUST:$/,/^#\. / { //!s/^/typeset -L / b KSH $_RB /^#\. VARIABLES RIGHTJUST:$/,/^#\. / { //!s/^/typeset -R / b KSH $_RB /^#\. VARIABLES ZEROFILL:$/,/^#\. / { //!s/^/typeset -Z / b KSH $_RB /^#\. VARIABLES INTEGER:$/,/^#\. / { //!s/^/typeset -i / b KSH $_RB /^#\. VARIABLES LOWERCASE:$/,/^#\. / { //!s/^/typeset -l / b KSH $_RB ${_isksh93:+ /^#\. VARIABLES NAMEREF:$/,/^#\. / { //!s/^/typeset -n / b KSH $_RB } ${_notagvars:+ /^#\. VARIABLES TAGGED:$/,/^#\. / { //!s/^/typeset -t / b KSH $_RB } /^#\. VARIABLES UPPERCASE:$/,/^#\. / { //!s/^/typeset -u / b KSH $_RB }} ${_addout[1]:+ ${_noisbourne:+ /^#\. ALIASES TRACKED:$/,/^#\. / { # Ksh Bug: ksh93 may omit "=" in alias -p output // !{ /=/!d s/^alias // s/^/alias -t -- / $_RB b KSH $_RB /^#\. ALIASES EXPORTED:$/,/^#\. / { # Warning: ksh93 does not implement exported aliases // !{ s/^alias // /^exit=/d ${_isbourne:+/^limit=/d} s/^/alias -x -- / $_RB b KSH $_RB ${_nofntrace:+ /^#\. FUNCTIONS TRACED:$/,/^#\. / { //!s/^/typeset -ft / b KSH $_RB }} /^#\. FUNCTIONS AUTOLOADED:$/,/^#\. / { //!s/^/typeset -fu / b KSH $_RB /^#\. FUNCTIONS EXPORTED:$/,/^#\. / { # Warning: ksh93 does not implement exported functions //!s/^/typeset -fx / b KSH $_RB } ${_addout[2]:+ /^#\. LIMITS SOFT:$/,/^#\. / { // !{ s/u/U/g; s/Unlimited/unlimited/ t treset1 : treset1 s/^time[^0-9u]*/ulimit -S -t /; t SH s/^data[^0-9u]*/ulimit -S -d / s/^file[^0-9u]*/ulimit -S -f /; t SH s/^stack[^0-9u]*/ulimit -S -s / s/^memory[^0-9u]*/ulimit -S -m /; t SH s/^core[^0-9u]*/ulimit -S -c / s/^v.*memory[^0-9u]*/ulimit -S -v /; t SH s/^.*descriptors[^0-9u]*/ulimit -S -n / s/^open [^0-9u]*/ulimit -S -n /; t SH # implemented in bash 1.x and 2.x: s/^pipe[^0-9u]*/ulimit -S -p / # implemented in bash 2.x: s/^.* processes[^0-9u]*/ulimit -S -u /; t SH d $_RB $_RB /^#\. LIMITS HARD:$/,/^#\. / { // !{ s/u/U/g; s/Unlimited/unlimited/ t treset2 : treset2 s/^time[^0-9u]*/ulimit -H -t /; t SH s/^data[^0-9u]*/ulimit -H -d / s/^file[^0-9u]*/ulimit -H -f /; t SH s/^stack[^0-9u]*/ulimit -H -s / s/^memory[^0-9u]*/ulimit -H -m /; t SH s/^core[^0-9u]*/ulimit -H -c / s/^v.*memory[^0-9u]*/ulimit -H -v /; t SH s/^.*descriptors[^0-9u]*/ulimit -H -n / s/^open [^0-9u]*/ulimit -H -n /; t SH # implemented in bash 1.x and 2.x: s/^pipe[^0-9u]*/ulimit -H -p / # implemented in bash 2.x: s/^.* processes[^0-9u]*/ulimit -H -u /; t SH d $_RB b SH $_RB /^#\. SHELL OPTIONS:$/,/^#\. / { // !{ /^C/d # Warning: only ksh93 has "interactive" and "restricted" options ${_noisksh93:+/^interactive /d; /^restricted /d} s/^\([^ ]*\) \{1,\\$_RB\(.*\)$/set -o \2\1/ s/ -o on/ -o / s/ -o off/ +o / # bourne shell? convert those kornshell options in common to bourne options: ${_isbourne:+ t treset3 : treset3 s/o allexport$/a/; t SH s/o errexit$/e/ # Warning: trackall and -h options are only approx equivalent s/o trackall$/h/; t SH s/o keyword$/k/ s/o noexec$/n/; t SH s/o noglob$/f/ s/o nounset$/u/; t SH s/o verbose$/v/ s/o xtrace$/x/; t SH d } $_RB b KSH $_RB #/^#\. STTY SETTINGS:$/,/^#\. / { # //!s/^/stty / # b SH #$_RB } : squote ${_quotedenv:+ : Xsq.0 /'/ { # Conjoin multi-line contents into one line, with newlines # replaced by the special token marker string "_!NL!_". : oneline s/'\\\\''/_!ESCSQ!_/g /^\\([^']*\\)'\\([^']*\\)'/ { s//\\1_!SQ!_\\2_!SQ!_/ /'/!b matched $_RB \$!N \$!b oneline : matched s/\\n/_!NL!_/g s/_!ESCSQ!_/'\\\\''/g $_RB : Xsq.1 } #XXX _noquotedenv ?? : eqlsign s/_!SQ!_/'/g ${ignore_uscore_vars:+/^_/d} # strip all _q* multi-line aliases and variables: /^_q/d /^#\. VARIABLES:$/,/^#\. / { // !{ /^set --/ !{ /=/!d; $_RB ${_isbourne:+/^_=/d} ${_uscore:+/^_=_qshadoe$/d} ${_showcode:+/^: \$-=/ s/[${_verbose:+v}${_xtrace:+x}]//} $_RB b SH $_RB ${_addout[1]:+ /^#\. TRAPS:$/,/^#\. / { # strip the DEBUG/ERR trap output // !{ / ${_debugtrap:+DEBUG}${_errtrap:+ERR}$/d # bourne shell? convert trap names to numerical equivalents: ${_isbourne:+$_names2nums} $_RB $_RB ${_noisbourne:+ /^#\. ALIASES:$/,/^#\. / { // !{ s/^alias // /^exit=/d /^limit=/d s/^/alias -- / $_RB b KSH $_RB }} : KSH : Xkorn # bourne shell? strip all commands specific to ksh: ${_isbourne:+/^#\. /!d} : SH : Xbourne /^_q/!{ w ./_qcenv p } !!!! #09 AUTOLOADED DEBUGGER FUNCTION /bin/sed -n "/^[$_TAB ]*$/!p" <|./_qshadoe function _qshadoe { # all arguments refer to the values of the calling environment. ((\$#==0)) && { # Ksh Bug: DEBUG trap broken in i86 Solaris 2.4 ksh[88i] #XXX \trap "\\trap '\ ${_showcode:+\\set ${_verbose:++o verbose }${_xtrace:++o xtrace}} _qshadoe \\\$LINENO \\\$? \"\\\$-\" \"\\\$0\" \\\$# \"\\\$@\" \"\\\$_\"\ ${_addout[1]:+ \"\$(\\trap)\"}' ${_debugtrap:+DEBUG}${_errtrap:+ERR}" EXIT \return \$? } # \$1=retval \$2=name \$3=\$_ [\$4=user supplied arg to exit cmd] ((\$#==4)) && \set -- \$4 \$2 \$3 # user-supplied arg takes precedence ((\$#==3)) && { \trap \ "\\set +o nounset${_verbose:+ +o verbose}${_xtrace:+ +o xtrace} _qcontrol=0 _qshadoe EOF \$1 \"\\\$-\" \"\$2\" \\\$# \"\\\$@\" \"\$3\"\ ${_addout[1]:+ \"\\\$(\\trap)\"}" EXIT \return \$1 } # \$1=lnno \$2=retval \$3=flags \$4=name \$5=argc \$6...=argv # last-2=\$_ last-1=traps [last=exit_retval] [[ \$1 != SOF && \$1 != EOF ]] && # bounds processing mandatory! { ${_showcode:+ # default EXIT trap: turn on verbose and/or xtrace option(s) \trap '\set ${_verbose:+-o verbose }${_xtrace:+-o xtrace}' EXIT } # Warning: as ksh93 executes the DEBUG trap _before_ each # line is executed, instead of _after_ as in ksh88, LINENO # will have been already reset before the DEBUG trap is # executed, _and_ LINENO will never expand to less than one. if ((\$1<=0)) then # LINENO is set less than or equal to 0: 'idling' state \trap - EXIT \return \$2 elif ((\$1<_qbgnlnno)) then \trap - EXIT \return \$2 elif ((\$1>_qendlnno)) then \trap \ '\trap - ${_debugtrap:+DEBUG}${_errtrap:+ERR}${_ignexit:+ EXIT}' EXIT \return \$2 elif ((_qcontrol<0)) then # force a display of env and post-increment _qcontrol \: elif ((_qcontrol>0)) then # pre-decrement _qcontrol, skip display of env? ((_qcontrol-=1)) && \return \$2 fi } # if got here: within bounds of code and conditions to debug \typeset -x _qoldpwd=\$OLDPWD _qpwd=\$PWD \cd -- \$_qdir || \exit 102 # Warning: real env ordered slightly differently than here displayed { \typeset -i _qnpp=\$5+1 _qroparams=": \\\$$=\$$ : \\\$!=\${!:-''$_RB : \\\$#=\$5 : \\\$-=\${3:-''$_RB : \\\$?=\${2:-0$_RB : \\\$0=\$4" \shift 5 print -r '$(eval /bin/date "\"+$_version\"")' # emit cwd and positional parameters print -n "cd -- '\$_qpwd'\\n#. VARIABLES:\\nset --" while ((_qnpp-=1)) do # Ksh Bug: necessary bec of poor quoting implemention if [[ \$1 = *\\'* ]] then _qrest=\$1 print -nr " '" while \: do _qsub=\${_qrest%%\\'*$_RB print -nr -- "\$_qsub'\\''" _qrest=\${_qrest#\$_qsub\\'$_RB [[ \$_qrest != *\\'* ]] && break done print -nr -- "\$_qrest'" else print -nr -- " '\$1'" fi \shift done # emit shell read-only special parameters print "\\n\$_qroparams" # emit variable=value pairs \eval "\\\\unset LINENO OLDPWD PS4 PWD RANDOM SECONDS _ _qnpp \ _qoldpwd _qpwd _qrest _qroparams _qsub OLDPWD='\$_qoldpwd' PWD='\$_qpwd' \ ${_uscore:+_=\\\$1 }\\\\typeset -${_tagvars:+t}" \shift print -r '#. ' ${_addout[0]:+ # emit variable attributes print -r '#. VARIABLES READONLY:' \typeset +r print '#. \\n#. VARIABLES EXPORTED:' \typeset +x print -r '#. ' ${_isksh93:+ print -r '#. VARIABLES ASSOCIATIVE:' \typeset +A # print '#. \\n#. VARIABLES CLASS:' # \typeset +C print '#. \\n#. VARIABLES EXPONENT:' \typeset +E print '#. \\n#. VARIABLES FLOAT:' \typeset +F print -r '#. ' } ${_noisbourne:+ print '#. VARIABLES FILENAME:' \typeset +H # use 'typeset -[LRZ] var=0000' style instead # of 'typeset -[LRZ]4 var' declaration style. print '#. \\n#. VARIABLES LEFTJUST:' \typeset +L print '#. \\n#. VARIABLES RIGHTJUST:' \typeset +R print '#. \\n#. VARIABLES ZEROFILL:' \typeset +Z print '#. \\n#. VARIABLES INTEGER:' \typeset +i print '#. \\n#. VARIABLES LOWERCASE:' \typeset +l ${_isksh93:+ print '#. \\n#. VARIABLES NAMEREF:' \typeset +n } ${_notagvars:+ print '#. \\n#. VARIABLES TAGGED:' # Warning: showing tagged variables is contingent # on no option -t traced variables being specified. \typeset +t } print '#. \\n#. VARIABLES UPPERCASE:' \typeset +u } print -r '#. ' } ${_addout[1]:+ # shell-level environment (generally user-specified): # traps, [aliases+attribs], functs[+attribs] print -r '#. TRAPS:' [[ -n \$1 ]] && print -r -- "\$1" \shift ${_noisbourne:+ print '#. \\n#. ALIASES:' # Ksh Bug: ksh86/88 wrongly shows tracked # aliases along with those user defined. # Ksh Bug: ksh93 fails to implement 'alias +'! ${_isksh93:+\alias -p}${_noisksh93:+\alias} print '#. \\n#. ALIASES TRACKED:' # Warning: ignore tracked aliases; see above. All tracked # aliases will be invalidated anyway whenever PATH is reset. # Ksh Bug: ksh93 fails to implement 'alias +t'! ${_isksh93:+\alias -pt}${_noisksh93:+\alias +t} ${_noisksh93:+ # Warning: ksh93 does not implement exported aliases #XXX then why does "alias -x" print out more information than "alias"?! # Ksh Bug: in ksh93, "typeset +fx" is still implemented, but "alias +x" is not! print '#. \\n#. ALIASES EXPORTED:' \alias +x }} print '#. \\n#. FUNCTIONS:' # Ksh Bug: ksh86/88 recognises bourne-style function # notation, but retains the kornshell-style function # environment for it. Warning: function body code # _must_ be delimited by right brace at left margin. # Warning: do not name a function the same as shprog! if [[ \$- = *f* ]] then \set +o noglob -- !(${_src##*/}|_q*) \set -o noglob else \set -- !(${_src##*/}|_q*) fi [[ \$1 != !* ]] && for _qinst { print -r "\$(<./\$_qinst)" $_RB print '#. \\n#. FUNCTIONS AUTOLOADED:' # Technically only a ksh feature, but necessary here # for the method function code is stored and accessed. # Warning: a function's attribs only show when defined. \typeset +fu ${_noisbourne:+ ${_nofntrace:+ print '#. \\n#. FUNCTIONS TRACED:' # Warning: showing traced functions is contingent # on no option -f traced functions being specified. \typeset +ft } #XXX${_noisksh93:+ print '#. \\n#. FUNCTIONS EXPORTED:' # Warning: ksh93 does not implement exported functions \typeset +fx #XXX} } print -r '#. ' } ${_addout[2]:+ # system-level environment (generally inherited): # umask, limits, shell options print -n '#. UMASK:\\numask ' \umask print '#. \\n#. LIMITS SOFT:' \ulimit -Sa print '#. \\n#. LIMITS HARD:' \ulimit -Ha print '#. \\n#. SHELL OPTIONS:' \set -o # print '#. \\n#. STTY SETTINGS:' # stty -g print -r '#. ' } $_RB | /bin/sed -n ${_addout:+-f ./_qe2disp.sed}${_noaddout:+'/^_q/ !{ ${_noquotedenv:+ #XXX NYI } w ./_qcenv p $_RB' } | /bin/cmp -s - ./_qoenv >|./_qcstamp # end-of-subshell: the function entry environment is restored [[ \$? != 0 || \$_qcontrol -lt 0 ]] && { # Displays the changed values of this environment # when value is new or changed, not when removed. ((_qcontrol<0)) && \let _qcontrol+=1 ${_errtrap:+ [[ \$1 != SOF && \$1 != EOF ]] && } { \: >|./_qdstamp /bin/diff ./_qoenv ./_qcenv | /bin/sed -n ' ${_showovalues:+ /^< \([^()=]\{1,\\$_RB\)=/ { s//\1 old value: / /^: /!s/^/: / b printit $_RB ${_addout[1]:+ /^< trap \(.*\) \([^ ]\{1,\\$_RB\)$/ { s//signal \2 handler code was: \1/ /^: /!s/^/: / b printit $_RB }} /^> / { s/// b printit $_RB d : printit ${env_newlines:+ s/_!NL!_/\\ /g } p' >|./_qdenv ${skip_initial_env:+ [[ \$1 != SOF ]] && } [[ -s ./_qdenv ]] && if ${_whenenv:+${_profile[1]:+\: }}\let 0 then \. ${_profile[1]:-/dev/null} else # default shadoe.trans: \eval print -r -- "\\"\$_qprompt\\"" # Warning: shprog can inadvertantly change vars VISUAL, EDITOR, and/or PAGER # Warning: 'more' will page only on sufficient output; using 'pg' as default: \eval \ SHELL=$_qshell TERM=$TERM \${VISUAL:-\${EDITOR:-\${PAGER:-pg}}} ./_qdenv print fi # If user has modified either env file since displayed, # then source that environment file to set the changes. # Warning: NFS makes modtime synchronization problematic for _qinst in c d { [[ -s ./_q\${_qinst}env && ./_q\${_qinst}stamp -ot ./_q\${_qinst}env ]] && { /bin/sed "s/_!NL!_/\\\\ /g s/^: /\\\\\\\\&/ s/^alias /\\\\\\\\&/ s/^cd /\\\\\\\\&/ s/^set /\\\\\\\\&/ s/^trap /\\\\\\\\&/ s/^typeset /\\\\\\\\&/ s/^ulimit /\\\\\\\\&/ s/^umask /\\\\\\\\&/ \\\$a\\\\ _qcontrol=\$_qcontrol" ./_q\${_qinst}env >|./_qtmp _qcontrol=9999 \trap \ 'time \. \$_qdir/_qtmp' EXIT #2>|/dev/null } } } /bin/mv ./_qcenv ./_qoenv } \cd -- \$_qoldpwd; \cd -- \$_qpwd ${_whentrap:+${_profile[1]:+ \. ${_profile[1]} }} [[ \$1 = EOF || \$1 -ge \$_qendlnno ]] 2>|/dev/null && \trap \ '\trap - ${_debugtrap:+DEBUG}${_errtrap:+ERR}${_ignexit:+ EXIT}' EXIT if [[ \$1 = EOF ]] then print -r 'done:\$?' >|\$_qdir/_qstatus if \eval \\\\typeset _lastarg=\\\${\$((\$5+7${_addout[1]:++1}))} [[ -n \$_lastarg ]] then # user specified an argument for an exit value \exit \$_lastarg else # default exit value is return value of previous cmd \exit \$2 fi else \return \$2 # propagate original return value fi } #>&2 !!!! #10 MUNGED SHELL SOURCE { print -r \ "#!${_isbourne:+$_kshpath}${_noisbourne:+$_qshell}${_qshopts:+ -$_qshopts} \trap - ${_debugtrap:+DEBUG}${_errtrap:+ERR} \: \${_qdir:=\${TMPDIR:-${TMPDIR:-/tmp}}/_q$$.d/} \: \${_qprompt='$_qprompt'} \: \${_qshell=$_qshell} \${_qshopts=$_qshopts} \: \${_qbgnlnno=${_qbgnlnno:-1}} # line number to begin debug \: \${_qmaxlnno:=$(/bin/sed -n \$= $_src)} # the number of lines in shprog \typeset -x _qdir _qprompt _qshell _qshopts \typeset -ix _qbgnlnno _qendlnno _qlnnodisp _qmaxlnno \typeset -ix _qcontrol=0 # if _qcontrol<0: force display and increment # _qcontrol=0: normal debug trap # _qcontrol>0: decrement and skip debug trap ((_qendlnno==0 || _qendlnno>_qmaxlnno-_qlnnodisp)) && \let _qendlnno=_qmaxlnno+_qlnnodisp \cd -- \$_qdir 2>&- || { print -nru2 \${0##*/}: error: bad or missing temporary directory if [[ /\$0 = */shadoe.sa ]] then print -ru2 ' (try using \"shadoe\" again)' else print -ru2 fi \exit 100 } # autoload debugger function responsible for displaying diffed environment FPATH=\$_qdir${FPATH:+:$FPATH} \typeset -fu _qshadoe #XXX or is it /bin/cmp? [[ $(alias -t | /bin/grep cmp) = cmp=/bin/cmp ]] $( [[ -n $_isksh93 && -n $PATH && $(whence cmp) != /bin/cmp ]] && { print -r \ '# modify PATH to allow ksh93 to use its shell builtin versions' print -r "PATH=/bin:$PATH" } ) ${_isbourne:+ # Warning: some bourne shells do not implement the 'limit' builtin \typeset -fx _qlimit function _qlimit { # Sh 'limit' and ksh 'ulimit' commands have similar but nonetheless # different syntax. This translates the first into the second form. \typeset field1=ON newopt=-f origopt softhard=-S oargv=\"\$*\" [[ \$1 = -h ]] && softhard=-H \shift if ((!\$#)) then newopt=-a field1= else \set -o noglob case \$1 in (c|d) print -ru2 limit: Ambiguous \return 1 ;; (co?(r?(e?(d?(u?(m?(p?(s?(i?(z?(e))))))))))) newopt=-c origopt=coredumpsize \shift ;; (cp?(u?(t?(i?(m?(e)))))) newopt=-t origopt=cputime \shift ;; (da?(t?(a?(s?(i?(z?(e))))))) newopt=-d origopt=datasize \shift ;; (de?(s?(c?(r?(i?(p?(t?(o?(r?(s)))))))))) newopt=-n origopt=descriptors \shift ;; (f?(i?(l?(e?(s?(i?(z?(e)))))))) newopt=-f origopt=filesize \shift ;; (m?(e?(m?(o?(r?(y?(u?(s?(e))))))))) newopt=-m origopt=memoryuse \shift ;; (s?(t?(a?(c?(k?(s?(i?(z?(e))))))))) newopt=-s origopt=stacksize \shift ;; (v?(m?(e?(m?(o?(r?(y))))))) newopt=-v origopt=vmemory \shift ;; (*) print -ru2 limit: No such resource \return 1 ;; esac # default units: # descriptors: limit: positive int ulimit: positive int # time: limit: [[hrs:]min:]sec ulimit: seconds # all others: limit: kbytes ulimit: blocks \typeset n t1 t2 [[ \$1 = +([0-9]) && \$2 = !([0-9])* ]] && \set \$1\$2 if [[ \$1 = unlimited ]] then n=unlimited elif [[ \$newopt = -n ]] then if [[ \$1 = +([0-9]) ]] then n=\$1 else print -ru2 \ limit: Improper or unknown scale factor \return 1 fi elif [[ \$newopt = -t ]] then case \$1 in (*([0-9])h?(o?(u?(r?(s))))) n=\${1%%h*$_RB \let n=3600*\${n:-0$_RB ;; (*([0-9])m?(i?(n?(u?(t?(e?(s))))))) n=\${1%%m*$_RB \let n=60*\${n:-0$_RB ;; (*([0-9])s?(e?(c?(o?(n?(d?(s))))))) n=\${1%%s*$_RB \let n=\${n:-0$_RB ;; (*:*) t1=\${1%%:*$_RB t2=\${1#*:$_RB \let n=60*\${t1:-0$_RB+\${t2:-0$_RB ;; (+([0-9])) \let n=\$1 ;; (*) print -ru2 \ limit: Improper or unknown scale factor \return 1 ;; esac # Warning: not all limit builtins implement the below: # Apparently the cputime limit has a granularity of # ten seconds with a one second grace period added on. #\let n=\$n/10*10+1 elif [[ \$1 = *([0-9])m?(e?(g?(a?(b?(y?(t?(e?(s)))))))) ]] then n=\${1%%m*$_RB \let n=2000*\${n:-0$_RB elif [[ \$1 = *([0-9])k?(i?(l?(o?(b?(y?(t?(e?(s)))))))) || \$1 = *([0-9])k?(b?(y?(t?(e?(s))))) ]] then n=\${1%%k*$_RB \let n=2*\${n:-0$_RB elif [[ \$1 = +([0-9]) ]] then \let n=2*\$1 else print -ru2 limit: Improper or unknown scale factor \return 1 fi fi ${VERBOSE:+print -ru2 [ limit \$oargv :=: ulimit \$softhard \$newopt \$n ]} [[ \$n = @(unlimited|+([0-9])) ]] && field1= if [[ -n \$field1 ]] then print -nr \"\$origopt $_TAB\" \ulimit \$softhard \$newopt \$n else \ulimit \$softhard \$newopt \$n ${_addout[2]:+ \trap '_qshadoe \$LINENO \ \$? \"\$-\" \"\$0\" \$# \"\$@\" \"\$_\" \"\$(\\trap)\"' EXIT } fi $_RB } # Warning: some tools (e.g. sed) will need fildes 9, else output will be null! \exec 9>&- #\ulimit -Sn $((($(\ulimit -Hn)+$(\ulimit -Sn))/2)) # more descriptors? \: >|./_qcstamp >|./_qdstamp >|./_qcenv >|./_qdenv [[ -f ./_qoenv ]] || \: >|./_qoenv print -r 'interrupted:\$?' >|./_qstatus #/bin/chmod u+t ./_qcenv ./_qcstamp ./_qdstamp \ ./_qdenv ./_qoenv${_addout:+ ./_qe2disp.sed} # faster disk I/O? /bin/rm -f ~/${_src##*/}.denv ~/${_src##*/}.env /bin/ln ${_symlinkok:+-s} \$_qdir/_qdenv ~/${_src##*/}.denv /bin/ln ${_symlinkok:+-s} \$_qdir/_qcenv ~/${_src##*/}.env \cd -- ~-; \cd -- ~+ ${_tagvars:+\typeset -t ${_tagvars[*]}} ${_addout[1]:+${_fntrace:+ # Ksh Bug: 'typeset -fx ...' resets 'typeset -fu ...' unless specified together \typeset -ftu ${_fntrace[*]} }} # Ksh Bug: parameter \"\$@\" below shouldn't, but does, set off any '-u' option. # it is assumed for all shells that the initial value of '_' is the shell path. _qcontrol=0 _qshadoe SOF \$? \"\$-\" \"\$0\" \$# \"\$@\" $_qshell \ ${_addout[1]:+ \"\$(\\trap)\"} ${_noisksh93:+${_source_ENV_script:+${ENV:+ # Warning: ksh93 sources ENV file only when interactive. # Warning: below may be redundantly sourced in standalone script shadoe.sa: [[ -f \$ENV && -r \$ENV ]] && ENV=$ENV \. \$ENV }}} ${_clearenv:+${_noisbourne:+${_noisksh93:+ # Needed for ksh88 as ksh93 doesn't read ENV file or implement exported aliases \unalias -- \$(\alias +) # Ksh Bug: ksh93 cannot execute this command # Ksh Bug: 'alias -- ' fails # Ksh Bug: ambiguous syntax possible for defining an alias for dash # Warning: aliases reinitialized below are only those documented as standard alias autoload='typeset -fu' functions='typeset -f' hash='alias -t -' \\ history='fc -l' integer='typeset -i' local=typeset nohup='nohup ' \\ r='fc -e -' stop='kill -STOP' suspend='kill -STOP $$' type='whence -v' }}} # Warning: do not use a return command outside of a function as an exit command LINENO=0 PS4='+[\$LINENO]:$_TAB' \alias exit='_qshadoe \$? \"\$0\" \"\$_\"' \ ${_isbourne:+ limit=_qlimit LINENO=0 \unset _ # Ksh Bug: cannot unset specialness} ${_autostart:+LINENO=0 _qshadoe # start the debugging trap} ${_qshopts:+$( # script is executed by a shell with option parameters [[ $_qshopts = *[nt]* ]] && print -r 'print -r done:\$? >|\$_qdir/_qstatus' print -r "LINENO=0 && \set -$_qshopts || \exit 101" )}\ LINENO=_qlnnodisp+1 \: $_qshell # reset var '_' to shell path" # now copy over (modified) shprog to be executed in above env. # Ksh Bug: "typeset -f" is broken for non-interactive shells! # All this nonsense would not have been necessary if ksh did not # mandate the "nolog" option in a non-interactive shell. Grrr! # Warning: ending rbrace _must_ be left justified in funct defn. if [[ -n ${_addout[1]} ]] then /bin/sed \ "${_noisbourne:+/^function[$_TAB ]\{1,\\$_RB\([A-Z_a-z][0-9A-Z_a-z]*\)/b seefn} /^\([A-Z_a-z][0-9A-Z_a-z]*\)[$_TAB ]*([$_TAB ]*)/b seefn b : seefn /^_q/b ${_noisbourne:+/^function[$_TAB ]\{1,\\${_RB}_q/b} ${print_funct_names:+w /dev/tty} /[$_TAB;&) ]}$/b havefn : getbody /\\n}/b havefn \$!N \$!b getbody : havefn t treset : treset ${_noisbourne:+ /^function[$_TAB ]\{1,\\$_RB\([A-Z_a-z][0-9A-Z_a-z]*\).*/s//\1~&/ t procfn } /^\([A-Z_a-z][0-9A-Z_a-z]*\).*/s//\1~&/ : procfn s:^\([^~]*\)~\(.*\)\$:_qcontrol=3;/bin/sed -n p<<\\\\\1_EOF\ >|\$_qdir/\1;LINENO=LINENO+1 _qcontrol=-1 \\\\typeset -fu \1\\ \2\\ \1_EOF: $_fncode" $_src else /bin/sed -n p $_src fi print -r \ '_qcontrol=0 exit # shadoe: ensure updated environment display at EOF' } >|./${_src##*/} #11 MAIN \trap : INT QUIT # shprog will handle signals \trap '\eval \\set -- "\"$(<$_qdir/_qstatus)\"" [[ -n $_dumpsrc ]] && /bin/sed -n p $_qdir/${_src##*/} >|./shadoe.sa && /bin/chmod +x ./shadoe.sa if [[ -n ${_profile[2]} ]] then \. ${_profile[2]} # sourced in env of debugger \exit $? else # default shadoe.post: ($1 is /(^interrupted|^done):$?/) \eval print -ru2 -- "\"$_qprompt\"" /bin/rm -f ~/${_src##*/}.denv ~/${_src##*/}.env /bin/cp $_qdir/_qoenv ./${_src##*/}.env 2>&- /bin/rm -fr $_qdir/ \exit 0 fi' EXIT # variables below are visible to the shprog to dynamically control the debugger \typeset -x _qbgnlnno _qcontrol _qdir _qendlnno \ _qlnnodisp _qprompt _qshell _qshopts \cd -- ~-; \cd -- ~+ # back to original directory; restore variable OLDPWD ${_profile[0]:+. ${_profile[0]} # sourced in env of debugger} \exec 9>&1 ( # Bourne sh gives default values to PATH, PS1, PS2, MAILCHECK, # and IFS. In addition, ksh88 gives a default value to TMOUT and # ksh93 adds to this default values for FCEDIT, PS3, and PS4. # [LOGNAME, MAIL, SHELL,] TERM, [TZ,] and USER are set by login(1). # VISUAL, EDITOR, and/or PAGER shall be exported, if defined. # Warning: if applicable, the shprog is execed by the "#!..." shell, # so an -s option may be necessary for non-conforming clone shells. \eval " ${_clearenv:+ /bin/env - ${_isksh93:+FCEDIT='$FCEDIT'} HOME='$HOME' \ ${LOGNAME+LOGNAME='$LOGNAME'} ${MAIL+MAIL='$MAIL'} \ MAILCHECK='$MAILCHECK' PATH='$PATH' PS1='$PS1' PS2='$PS2' \ ${_isksh93:+PS3='$PS3' PS4='$PS4'} ${SHELL+SHELL='$SHELL'} \ TERM='$TERM' ${TZ+TZ='$TZ'} USER='$USER' ${_noisbourne:+TMOUT='$TMOUT'}\ } ENV= IFS='${IFS# ,}' ${EDITOR+EDITOR='$EDITOR'} \ ${PAGER+PAGER='$PAGER'} ${VISUAL+VISUAL='$VISUAL'} \ ${_isbourne:+$_kshpath}${_noisbourne:+$_qshell}${_qshopts:+ -$_qshopts}\ -- $_qdir/${_src##*/} \"\$@\"" print -r -- $? >|$_qdir/_qtmp ) 2>&1 1>&9 9>&- | ( # Warning: file "shadoe.out" will need to be pruned every so often eval /bin/date "\"+%n$_version\"" >>./shadoe.out 2>&- /bin/tee -a ./shadoe.out 2>&- \exit $(<$_qdir/_qtmp) ) 1>&2 9>&-