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