## ## OSSP due - Dynamic User Environment ## Copyright (c) 1994-2004 Ralf S. Engelschall ## Copyright (c) 1994-2004 The OSSP Project ## ## This file is part of OSSP due, a dynamic user environment ## which can found at http://www.ossp.org/pkg/tool/due/ ## ## Permission to use, copy, modify, and distribute this software for ## any purpose with or without fee is hereby granted, provided that ## the above copyright notice and this permission notice appear in all ## copies. ## ## THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED ## WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ## MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ## IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR ## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF ## USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ## OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ## SUCH DAMAGE. ## ## due.root.sh: DUE module for root command execution ## # generate shell script for re-evaluation of command arguments # input: foo 'bar baz' quux (3 args) # output: "foo \"bar baz\" quux" (1 arg) function _arg2sh () { local opt_e=no local opt_t=no local opt OPTIND=1 while getopts et opt; do case ${opt} in e ) opt_e=yes ;; t ) opt_t=yes ;; esac done shift $(($OPTIND - 1)) local cmd="" local arg for arg in "$@"; do # NOTICE: there are three(!) escaping layers here: # - escape layer 1: backticks (`..xx..`) # - escape layer 2: quotes ('..xx..') # - escape layer 3: sed regex (s;..xx..;..xx..;) local orig=$arg if [ ${opt_e} = yes ]; then arg=`echo "@${arg}" | sed -e 's;^@;;' -e 's;\\\\;\\\\\\\\;g' -e 's;\\(["]\\);\\\\\\1;g'` elif [ ${opt_t} = yes ]; then arg=`echo "@${arg}" | sed -e 's;^@;;' -e 's;\\\\;\\\\\\\\;g' -e 's;\\(["!\$\`]\\);\\\\\\1;g'` fi local quote=no if [ "${arg}" != "${orig}" ]; then quote=yes else quote=`echo "@${arg}" | sed -e 's;^@.*[ ].*\$;yes;' -e 's;^@.*;no;'` fi if [ ${quote} = yes ]; then arg=`echo "@${arg}" |\ sed -e 's;^@\([A-Z][A-Z0-9_]*\)=\(.*\)$;\1="\2";' \ -e 's;^@\(.*\)$;"\1";'` fi cmd="${cmd}${cmd:+ }${arg}" done printf "%s" "${cmd}" # intentionally not echo(1) } # generate shell script for re-evaluation of environment variables # input: PATH HOME (2 args) # output: "PATH=\"...\"; HOME=\"...\"" (1 arg) function _env2sh () { local cmd="" local arg for arg in "$@"; do local val eval "val=\"\$${arg}\"" # NOTICE: there are three(!) escaping layers here, too. val=`echo "@${val}" | sed -e 's;^@;;' -e 's;\\\\;\\\\\\\\;g' -e 's;\\(["!\$\`]\\);\\\\\\1;g'` cmd="${cmd}${cmd:+; }${arg}=\"${val}\"" done printf "%s" "${cmd}" # intentionally not echo(1) } # smart dealing with temporary root privileges function root () { # default operation if [ $# -eq 0 ]; then set -- -i fi # parse command line options local opt_i=no # interactive shell local opt_l=no # last command-line local opt_e=no # remote expansion mode local opt OPTIND=1 while getopts ileh opt; do case ${opt} in i ) opt_i=yes ;; l ) opt_l=yes ;; e ) opt_e=yes ;; h ) echo "root:Usage: root [-h] [-l] [-e] command"; return 0 ;; ? ) echo "root:Error: invalid command line"; return 1 ;; esac done shift $(($OPTIND - 1)) # determine action(s) local prolog=":" local epilog=":" local command if [ ${opt_i} = yes ]; then # enter interactive session with root privileges local xtermcontrol=`find_tool xtermcontrol xtermcolors` if [ -n "${xtermcontrol}" ]; then prolog="${xtermcontrol} --cursor='#cc3333'" epilog="${xtermcontrol} --cursor='#000000'" command="PS1=\"\\[\\e[31;1m\\]\\u\\[\\e[0m\\]@\\h:\\w\\n\\\\\\$ \"; export PS1" fi command="${command}${command:+; }exec ${SHELL} --norc --noprofile" elif [ ${opt_l} = yes -a ${opt_e} = yes ]; then eval "set -- $(builtin history 2 | sed -n -e '1p' | cut -c8-)" command=$(_arg2sh -e -- "$@") elif [ ${opt_l} = yes ]; then # execute last command-line with root privileges command=$(builtin history 2 | sed -n -e '1p' | cut -c8-) elif [ ${opt_e} = yes ]; then # execute given command-line with root privileges (expansion mode) command=$(_arg2sh -e -- "$@") else # execute given command-line with root privileges (transparent mode) command=$(_arg2sh -t -- "$@") fi # generate action command local cmd=$(_env2sh ${ROOT_ENV:-PATH MANPATH INFOPATH LD_LIBRARY_PATH TERM HOME EDITOR PAGER LOGNAME USER}) cmd="${cmd}; cd ${PWD} && ${command}" cmd=$(_arg2sh -t -- "${cmd}") eval ${prolog}; ssh -t -q -x root@${HOSTNAME} ${SHELL} -c "${cmd}"; rv=$?; eval ${epilog} # exit with return value of remote command return $rv }