Posted to tcl by rahl at Wed Nov 16 10:46:42 GMT 2022view pretty

#!/bin/expect -f

# Send SIGINT and exit
proc abort {code} {
    # TODO: Is the SIGINT really necessary?
    # Equivalent to Ctrl-C
    send \x03
    exit $code
}

if {[llength $argv] < 3} {
    puts "Usage: autoborg.exp user passwd-file command [args]"
    exit 33
}

set command [lassign $argv user passwd]

set fp [open "${passwd}" r]
set data [split [read $fp] \n]
close $fp

set pass_idx 0

spawn sudo -u $user {*}$command

# Handle ssh, sudo and doas passphrase/words
set pass_request [join [list {*}{
    "Enter passphrase for key '.*': "
    "\[sudo\] password for .*: "
    "doas \(.*\) password: "
}] |]

expect {
    -re $pass_request {
        if {$pass_idx >= [llength $data]} {
            abort 34
        }

        set server_pass [lindex $data $pass_idx]
        send "${server_pass}\r"

        incr pass_idx
        exp_continue
    }

    "Authentication failed" {
        abort 35
    }

    timeout { abort 36 }
    eof
}

lassign [wait] pid spawnid os_error_flag value

if {$os_error_flag == 0} {
    puts "exit status: $value"
} else {
    puts "errno: $value"
}

# - borg
#   0:            success
#   1:            warning
#   2:            error
#   128+N:        killed by signal N
#
# - sudo
#   pass through: success
#   1:            auth failure (maybe other)
#
# - doas
#   0:            success
#   >0:           error passthrough
#
# - ssh
#   pass through: success
#   255:          error
#
# - autoborg (this script)
#   33:           error - incorrect arg count
#   34:           abort - not enough passphrases
#   35:           abort - authentication failure
#   36:           abort - timeout
#
exit $value