Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/bin/sh
- #-
- ############################################################ IDENT(1)
- #
- # $Title: Script to provide interactive shell that answers sudo prompts $
- # $Copyright: 2019 Devin Teske. All rights reserved. $
- # $FrauBSD$
- #
- ############################################################ ENVIRONMENT
- : "${USER:=$( id -nu )}"
- : "${HOSTNAME:=$( hostname )}"
- export USER HOSTNAME
- SUDO_PROMPT="[sudo] Password:"
- SUDO_PROMPT_RE="\\[sudo\\] [Pp]assword( for $USER)?: *"
- export SUDO_PROMPT SUDO_PROMPT_RE
- ############################################################ GLOBALS
- pgm="${0##*/}" # Program basename
- progdir="${0%/*}" # Program directory
- #
- # Global exit status
- #
- SUCCESS=0
- FAILURE=1
- ############################################################ FUNCTIONS
- usage()
- {
- local optfmt="\t%-5s %s\n"
- exec >&2
- printf "Usage: %s [-h]\n" "$pgm"
- printf "Options:\n"
- printf "$optfmt" "-h" "Print usage statement to stderr and exit."
- die
- }
- die()
- {
- local fmt="$1"
- if [ "$fmt" ]; then
- shift 1 # fmt
- printf "%s: $fmt\n" "$pgm" "$@"
- fi
- exit $FAILURE
- }
- make_expect()
- {
- local var=$1
- shift 1 # var
- exec 9<<-EOF
- set okprompt "$pgm> "
- set timeout -1
- set user $::env(USER)
- set hostname $::env(HOSTNAME)
- set argv $::env(COMMAND)
- $( n=1; for key_value in "$@"; do
- prompt="${key_value%%=*}"
- re="${key_value#*=}"
- printf '\nset prompt%u\t$::env(%s)' $n $prompt
- printf '\nset promptre%u\t$::env(%s)' $n $re
- n=$(( $n + 1 ))
- done )
- regsub -all {\..*} \$hostname {} hostname
- set shell_prompts ""
- foreach shell_prompt [list \
- [subst -nocommand -nobackslashes \
- {\$user@\$hostname[^\n\r]*$}] \
- [subst -nocommand -nobackslashes \
- {\$user@\$hostname[^\n\r]*[#%>]}] \
- ] {
- set shell_prompts [subst -nocommand -nobackslashes \
- {\$shell_prompts|\$shell_prompt}]
- }
- set shell_prompts [string range \$shell_prompts 1 \
- [string length \$shell_prompts]]
- set prompts ""
- foreach prompt [list \
- [subst -nocommand -nobackslashes {\$shell_prompts}] \
- $( n=0; for key_value in "$@"; do
- n=$(( $n + 1 ))
- printf '[subst %s {$%s}] \\\n' \
- "-nocommand -nobackslashes" promptre$n
- done ) \
- ] {
- set prompts [subst -nocommand -nobackslashes \
- {\$prompts|\$prompt}]
- }
- set prompts [string range \$prompts 1 [string length \$prompts]]
- fconfigure stdout -buffering none
- spawn {*}\$argv
- # Get prompt answers
- stty -echo
- $( n=1; for key_value in "$@"; do
- printf 'send_user "$%s"\n' prompt$n
- printf 'expect_tty eof exit -re {([[:print:]]*)\\n}\n'
- printf 'send_user "\\n"\n'
- printf 'set %s $expect_out(1,string)\n' answer$n
- done )
- stty echo
- proc abort {} {
- log_user 0
- exit 0
- }
- while (1) {
- expect eof abort -re [subst -nocommands -nobackslashes \
- {[^\n\r]*(\$prompts)\s*$}]
- set buffer \$expect_out(0,string)
- # shell prompt(s)
- if {[regexp [subst -nocommands -nobackslashes \
- {^[^\n\r]*(\$shell_prompts)\s*$}] \$buffer]} \
- {
- send_tty \$okprompt
- interact eof abort \
- -nobuffer -re {[\r\003\004]} {return} \
- }
- # defined prompt(s)
- $( n=0; for key_value in "$@"; do
- n=$(( $n + 1 ))
- printf 'if {[regexp [subst %s {^$%s$}] $buffer]} ' \
- "-nocommands -nobackslashes" promptre$n
- printf '{ send "$%s\\r" }\n' answer$n
- done )
- }
- EOF
- eval $var='$( cat <&9 )'
- }
- ############################################################ MAIN
- #
- # Parse command-line options
- #
- while getopts h flag; do
- case "$flag" in
- *) usage # NOTREACHED
- esac
- done
- shift $(( $OPTIND - 1 ))
- #
- # Run command
- #
- make_expect EXPECT_SUDO SUDO_PROMPT=SUDO_PROMPT_RE
- export EXPECT_SUDO COMMAND="${*:-$( ps -o ucomm= -p $PPID )} -l"
- expect -c 'eval $::env(EXPECT_SUDO)'
- ################################################################################
- # END
- ################################################################################
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement