/usr/bin/expect_kibitz is in expect 5.45-7.
This file is owned by root:root, with mode 0o755.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 | #!/bin/sh
# -*- tcl -*-
# The next line is executed by /bin/sh, but not tcl \
exec tclsh8.6 "$0" ${1+"$@"}
package require Expect
# allow another user to share a shell (or other program) with you
# See kibitz(1) man page for complete info.
# Author: Don Libes, NIST
# Date written: December 5, 1991
# Date last editted: October 19, 1994
# Version: 2.11
exp_version -exit 5.0
# if environment variable "EXPECT_PROMPT" exists, it is taken as a regular
# expression which matches the end of your login prompt (but does not other-
# wise occur while logging in).
set prompt "(%|#|\\$) $" ;# default prompt
set noproc 0
set tty "" ;# default if no -tty flag
set allow_escape 1 ;# allow escapes if true
set escape_char \035 ;# control-right-bracket
set escape_printable "^\]"
set verbose 1 ;# if true, describe what kibitz is doing
set kibitz "kibitz" ;# where kibitz lives if some unusual place.
;# this must end in "kibitz", but can have
;# things in front (like directory names).
#set proxy "kibitz" ;# uncomment and set if you want kibitz to use
;# some other account on remote systems
# The following code attempts to intuit whether cat buffers by default.
# The -u flag is required on HPUX (8 and 9) and IBM AIX (3.2) systems.
if {[file exists $exp_exec_library/cat-buffers]} {
set catflags "-u"
} else {
set catflags ""
}
# If this fails, you can also force it by commenting in one of the following.
# Or, you can use the -catu flag to the script.
#set catflags ""
#set catflags "-u"
# Some flags must be passed onto the remote kibitz process. They are stored
# in "kibitz_flags". Currently, they include -tty and -silent.
set kibitz_flags ""
while {[llength $argv]>0} {
set flag [lindex $argv 0]
switch -- $flag \
"-noproc" {
set noproc 1
set argv [lrange $argv 1 end]
} "-catu" {
set catflags "-u"
set argv [lrange $argv 1 end]
} "-tty" {
set tty [lindex $argv 1]
set argv [lrange $argv 2 end]
set kibitz_flags "$kibitz_flags -tty $tty"
} "-noescape" {
set allow_escape 0
set argv [lrange $argv 1 end]
} "-escape" {
set escape_char [lindex $argv 1]
set escape_printable $escape_char
set argv [lrange $argv 2 end]
} "-silent" {
set verbose 0
set argv [lrange $argv 1 end]
set kibitz_flags "$kibitz_flags -silent"
} "-proxy" {
set proxy [lindex $argv 1]
set argv [lrange $argv 2 end]
} default {
break
}
}
if {([llength $argv]<1) && ($noproc==0)} {
send_user "usage: kibitz \[args] user \[program ...]\n"
send_user " or: kibitz \[args] user@host \[program ...]\n"
exit
}
log_user 0
set timeout -1
set user [lindex $argv 0]
if {[string match -r $user]} {
send_user "KRUN" ;# this tells user_number 1 that we're running
;# and to prepare for possible error messages
set user_number 3
# need to check that it exists first!
set user [lindex $argv 1]
} else {
set user_number [expr 1+(0==[string first - $user])]
}
# at this point, user_number and user are correctly determined
# User who originated kibitz session has user_number == 1 on local machine.
# User who is responding to kibitz has user_number == 2.
# User who originated kibitz session has user_number == 3 on remote machine.
# user 1 invokes kibitz as "kibitz user[@host]"
# user 2 invokes kibitz as "kibitz -####" (some pid).
# user 3 invokes kibitz as "kibitz -r user".
# uncomment for debugging: leaves each user's session in a file: 1, 2 or 3
#exec rm -f $user_number
#exp_internal -f $user_number 0
set user2_islocal 1 ;# assume local at first
# later move inside following if $user_number == 1
# return true if x is a prefix of xjunk, given that prefixes are only
# valid at . delimiters
# if !do_if0, skip the whole thing - this is here just to make caller simpler
proc is_prefix {do_if0 x xjunk} {
if 0!=$do_if0 {return 0}
set split [split $xjunk .]
for {set i [expr [llength $split]-1]} {$i>=0} {incr i -1} {
if {[string match $x [join [lrange $split 0 $i] .]]} {return 1}
}
return 0
}
# get domainname. Unfortunately, on some systems, domainname(1)
# returns NIS domainname which is not the internet domainname.
proc domainname {} {
# open pops stack upon failure
set rc [catch {open /etc/resolv.conf r} file]
if {$rc==0} {
while {-1!=[gets $file buf]} {
if 1==[scan $buf "domain %s" name] {
close $file
return $name
}
}
close $file
}
# fall back to using domainname
if {0==[catch {exec domainname} name]} {return $name}
error "could not figure out domainname"
}
if $user_number==1 {
if $noproc==0 {
if {[llength $argv]>1} {
set pid [eval spawn [lrange $argv 1 end]]
} else {
# if running as CGI, shell may not be set!
set shell /bin/sh
catch {set shell $env(SHELL)}
set pid [spawn $shell]
}
set shell $spawn_id
}
# is user2 remote?
regexp (\[^@\]*)@*(.*) $user ignore tmp host
set user $tmp
if ![string match $host ""] {
set h_rc [catch {exec hostname} hostname]
set d_rc [catch domainname domainname]
if {![is_prefix $h_rc $host $hostname]
&& ![is_prefix $d_rc $host $hostname.$domainname]} {
set user2_islocal 0
}
}
if !$user2_islocal {
if $verbose {send_user "connecting to $host\n"}
if ![info exists proxy] {
proc whoami {} {
global env
if {[info exists env(USER)]} {return $env(USER)}
if {[info exists env(LOGNAME)]} {return $env(LOGNAME)}
if {![catch {exec whoami} user]} {return $user}
if {![catch {exec logname} user]} {return $user}
# error "can't figure out who you are!"
}
set proxy [whoami]
}
spawn rlogin $host -l $proxy -8
set userin $spawn_id
set userout $spawn_id
catch {set prompt $env(EXPECT_PROMPT)}
set timeout 120
expect {
assword: {
stty -echo
send_user "password (for $proxy) on $host: "
set old_timeout $timeout; set timeout -1
expect_user -re "(.*)\n"
send_user "\n"
set timeout $old_timeout
send "$expect_out(1,string)\r"
# bother resetting echo?
exp_continue
} incorrect* {
send_user "invalid password or account\n"
exit
} "TERM = *) " {
send "\r"
exp_continue
} timeout {
send_user "connection to $host timed out\n"
exit
} eof {
send_user "connection to host failed: $expect_out(buffer)"
exit
} -re $prompt
}
if {$verbose} {send_user "starting kibitz on $host\n"}
# the kill protects user1 from receiving user3's
# prompt if user2 exits via expect's exit.
send "$kibitz $kibitz_flags -r $user;kill -9 $$\r"
expect {
-re "kibitz $kibitz_flags -r $user.*KRUN" {}
-re "kibitz $kibitz_flags -r $user.*(kibitz\[^\r\]*)\r" {
send_user "unable to start kibitz on $host: \"$expect_out(1,string)\"\n"
send_user "try rlogin by hand followed by \"kibitz $user\"\n"
exit
}
timeout {
send_user "unable to start kibitz on $host: "
set expect_out(buffer) "timed out"
set timeout 0; expect -re .+
send_user $expect_out(buffer)
exit
}
}
expect {
-re ".*\n" {
# pass back diagnostics
# should really strip out extra cr
send_user $expect_out(buffer)
exp_continue
}
KABORT exit
default exit
KDATA
}
}
}
if {$user_number==2} {
set pid [string trimleft $user -]
}
set local_io [expr ($user_number==3)||$user2_islocal]
if {$local_io||($user_number==2)} {
if {0==[info exists pid]} {set pid [pid]}
set userinfile /tmp/exp0.$pid
set useroutfile /tmp/exp1.$pid
}
proc prompt1 {} {
return "kibitz[info level].[history nextid]> "
}
set esc_match {}
if {$allow_escape} {
set esc_match {
$escape_char {
send_user "\nto exit kibitz, enter: exit\n"
send_user "to suspend kibitz, press appropriate job control sequence\n"
send_user "to return to kibitzing, enter: return\n"
interpreter
send_user "returning to kibitz\n"
}
}
}
proc prompt1 {} {
return "kibitz[info level].[history nextid]> "
}
set timeout -1
# kibitzer executes following code
if {$user_number==2} {
# for readability, swap variables
set tmp $userinfile
set userinfile $useroutfile
set useroutfile $tmp
if ![file readable $userinfile] {
send_user "Eh? No one is asking you to kibitz.\n"
exit -1
}
spawn -open [open "|cat $catflags < $userinfile" "r"]
set userin $spawn_id
spawn -open [open $useroutfile w]
set userout $spawn_id
# open will hang until other user's cat starts
stty -echo raw
if {$allow_escape} {send_user "Escape sequence is $escape_printable\r\n"}
# While user is reading message, try to delete other fifo
catch {exec rm -f $userinfile}
eval interact $esc_match \
-output $userout \
-input $userin
exit
}
# only user_numbers 1 and 3 execute remaining code
proc abort {} {
# KABORT tells user_number 1 that user_number 3 has run into problems
# and is exiting, and diagnostics have been returned already
if {$::user_number==3} {send_user KABORT}
exit
}
if {$local_io} {
proc mkfifo {f} {
if 0==[catch {exec mkfifo $f}] return ;# POSIX
if 0==[catch {exec mknod $f p}] return
# some systems put mknod in wierd places
if 0==[catch {exec /usr/etc/mknod $f p}] return ;# Sun
if 0==[catch {exec /etc/mknod $f p}] return ;# AIX, Cray
puts "Couldn't figure out how to make a fifo - where is mknod?"
abort
}
proc rmfifos {} {
global userinfile useroutfile
catch {exec rm -f $userinfile $useroutfile}
}
trap {rmfifos; exit} {SIGINT SIGQUIT SIGTERM}
# create 2 fifos to communicate with other user
mkfifo $userinfile
mkfifo $useroutfile
# make sure other user can access despite umask
exec chmod 666 $userinfile $useroutfile
if {$verbose} {send_user "asking $user to type: kibitz -$pid\n"}
# can't use exec since write insists on being run from a tty!
set rc [catch {
system echo "Can we talk? Run: \"kibitz -$pid\"" | \
write $user $tty
}
]
if {$rc} {rmfifos;abort}
spawn -open [open $useroutfile w]
set userout $spawn_id
# open will hang until other user's cat starts
spawn -open [open "|cat $catflags < $userinfile" "r"]
set userin $spawn_id
catch {exec rm $userinfile}
}
stty -echo raw
if {$user_number==3} {
send_user "KDATA" ;# this tells user_number 1 to send data
interact {
-output $userout
-input $userin eof {
wait -i $userin
return -tcl
} -output $user_spawn_id
}
} else {
if {$allow_escape} {send_user "Escape sequence is $escape_printable\r\n"}
if {$noproc} {
interact {
-output $userout
-input $userin eof {wait -i $userin; return}
-output $user_spawn_id
}
} else {
eval interact $esc_match {
-output $shell \
-input $userin eof {
wait -i $userin
close -i $shell
return
} -output $shell \
-input $shell eof {
close -i $userout
wait -i $userout
return
} -output "$user_spawn_id $userout"
}
wait -i $shell
}
}
if {$local_io} rmfifos
|