Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / devtools / amd64 / bin / rftp
CommitLineData
920dae64
AT
1#!/bin/sh
2# \
3exec expect -f "$0" ${1+"$@"}
4# rftp - ftp a directory hierarchy (i.e. recursive ftp)
5# Version 2.10
6# Don Libes, NIST
7exp_version -exit 5.0
8
9# rftp is much like ftp except that the command ~g copies everything in
10# the remote current working directory to the local current working
11# directory. Similarly ~p copies in the reverse direction. ~l just
12# lists the remote directories.
13
14# rftp takes an argument of the host to ftp to. Username and password
15# are prompted for. Other ftp options can be set interactively at that
16# time. If your local ftp understands .netrc, that is also used.
17
18# ~/.rftprc is sourced after the user has logged in to the remote site
19# and other ftp commands may be sent at that time. .rftprc may also be
20# used to override the following rftp defaults. The lines should use
21# the same syntax as these:
22
23set file_timeout 3600 ;# timeout (seconds) for retrieving files
24set timeout 1000000 ;# timeout (seconds) for other ftp dialogue
25set default_type binary ;# default type, i.e., ascii, binary, tenex
26set binary {} ;# files matching are transferred as binary
27set ascii {} ;# as above, but as ascii
28set tenex {} ;# as above, but as tenex
29
30# The values of binary, ascii and tenex should be a list of (Tcl) regular
31# expressions. For example, the following definitions would force files
32# ending in *.Z and *.tar to be transferred as binaries and everything else
33# as text.
34
35# set default_type ascii
36# set binary {*.Z *.tar}
37
38# If you are on a UNIX machine, you can probably safely ignore all of this
39# and transfer everything as "binary".
40
41# The current implementation requires that the source host be able to
42# provide directory listings in UNIX format. Hence, you cannot copy
43# from a VMS host (although you can copy to it). In fact, there is no
44# standard for the output that ftp produces, and thus, ftps that differ
45# significantly from the ubiquitous UNIX implementation may not work
46# with rftp (at least, not without changing the scanning and parsing).
47
48####################end of documentation###############################
49
50match_max -d 100000 ;# max size of a directory listing
51
52# return name of file from one line of directory listing
53proc getname {line} {
54 # if it's a symbolic link, return local name
55 set i [lsearch $line "->"]
56 if {-1==$i} {
57 # not a sym link, return last token of line as name
58 return [lindex $line [expr [llength $line]-1]]
59 } else {
60 # sym link, return "a" of "a -> b"
61 return [lindex $line [expr $i-1]]
62 }
63}
64
65proc putfile {name} {
66 global current_type default_type
67 global binary ascii tenex
68 global file_timeout
69
70 switch -- $name $binary {set new_type binary} \
71 $ascii {set new_type ascii} \
72 $tenex {set new_type tenex} \
73 default {set new_type $default_type}
74
75 if {$current_type != $new_type} {
76 settype $new_type
77 }
78
79 set timeout $file_timeout
80 send "put $name\r"
81 expect timeout {
82 send_user "ftp timed out in response to \"put $name\"\n"
83 exit
84 } "ftp>*"
85}
86
87proc getfile {name} {
88 global current_type default_type
89 global binary ascii tenex
90 global file_timeout
91
92 switch -- $name $binary {set new_type binary} \
93 $ascii {set new_type ascii} \
94 $tenex {set new_type tenex} \
95 default {set new_type $default_type}
96
97 if {$current_type != $new_type} {
98 settype $new_type
99 }
100
101 set timeout $file_timeout
102 send "get $name\r"
103 expect timeout {
104 send_user "ftp timed out in response to \"get $name\"\n"
105 exit
106 } "ftp>*"
107}
108
109# returns 1 if successful, 0 otherwise
110proc putdirectory {name} {
111 send "mkdir $name\r"
112 expect "550*denied*ftp>*" {
113 send_user "failed to make remote directory $name\n"
114 return 0
115 } timeout {
116 send_user "timed out on make remote directory $name\n"
117 return 0
118 } -re "(257|550.*exists).*ftp>.*"
119 # 550 is returned if directory already exists
120
121 send "cd $name\r"
122 expect "550*ftp>*" {
123 send_user "failed to cd to remote directory $name\n"
124 return 0
125 } timeout {
126 send_user "timed out on cd to remote directory $name\n"
127 return 0
128 } -re "2(5|0)0.*ftp>.*"
129 # some ftp's return 200, some return 250
130
131 send "lcd $name\r"
132 # hard to know what to look for, since my ftp doesn't return status
133 # codes. It is evidentally very locale-dependent.
134 # So, assume success.
135 expect "ftp>*"
136 putcurdirectory
137 send "lcd ..\r"
138 expect "ftp>*"
139 send "cd ..\r"
140 expect timeout {
141 send_user "failed to cd to remote directory ..\n"
142 return 0
143 } -re "2(5|0)0.*ftp>.*"
144
145 return 1
146}
147
148# returns 1 if successful, 0 otherwise
149proc getdirectory {name transfer} {
150 send "cd $name\r"
151 # this can fail normally if it's a symbolic link, and we are just
152 # experimenting
153 expect "550*$name*ftp>*" {
154 send_user "failed to cd to remote directory $name\n"
155 return 0
156 } timeout {
157 send_user "timed out on cd to remote directory $name\n"
158 return 0
159 } -re "2(5|0)0.*ftp>.*"
160 # some ftp's return 200, some return 250
161
162 if {$transfer} {
163 send "!mkdir $name\r"
164 expect "denied*" return timeout return "ftp>"
165 send "lcd $name\r"
166 # hard to know what to look for, since my ftp doesn't return
167 # status codes. It is evidentally very locale-dependent.
168 # So, assume success.
169 expect "ftp>*"
170 }
171 getcurdirectory $transfer
172 if {$transfer} {
173 send "lcd ..\r"
174 expect "ftp>*"
175 }
176 send "cd ..\r"
177 expect timeout {
178 send_user "failed to cd to remote directory ..\n"
179 return 0
180 } -re "2(5|0)0.*ftp>.*"
181
182 return 1
183}
184
185proc putentry {name type} {
186 switch -- $type d {
187 # directory
188 if {$name=="." || $name==".."} return
189 putdirectory $name
190 } - {
191 # file
192 putfile $name
193 } l {
194 # symlink, could be either file or directory
195 # first assume it's a directory
196 if {[putdirectory $name]} return
197 putfile $name
198 } default {
199 send_user "can't figure out what $name is, skipping\n"
200 }
201}
202
203proc getentry {name type transfer} {
204 switch -- $type d {
205 # directory
206 if {$name=="." || $name==".."} return
207 getdirectory $name $transfer
208 } - {
209 # file
210 if {!$transfer} return
211 getfile $name
212 } l {
213 # symlink, could be either file or directory
214 # first assume it's a directory
215 if {[getdirectory $name $transfer]} return
216 if {!$transfer} return
217 getfile $name
218 } default {
219 send_user "can't figure out what $name is, skipping\n"
220 }
221}
222
223proc putcurdirectory {} {
224 send "!/bin/ls -alg\r"
225 expect timeout {
226 send_user "failed to get directory listing\n"
227 return
228 } "ftp>*"
229
230 set buf $expect_out(buffer)
231
232 while {1} {
233 # if end of listing, succeeded!
234 if 0==[regexp "(\[^\n]*)\n(.*)" $buf dummy line buf] return
235
236 set token [lindex $line 0]
237 switch -- $token !/bin/ls {
238 # original command
239 } total {
240 # directory header
241 } . {
242 # unreadable
243 } default {
244 # either file or directory
245 set name [getname $line]
246 set type [string index $line 0]
247 putentry $name $type
248 }
249 }
250}
251
252# look at result of "dir". If transfer==1, get all files and directories
253proc getcurdirectory {transfer} {
254 send "dir\r"
255 expect timeout {
256 send_user "failed to get directory listing\n"
257 return
258 } "ftp>*"
259
260 set buf $expect_out(buffer)
261
262 while {1} {
263 regexp "(\[^\n]*)\n(.*)" $buf dummy line buf
264
265 set token [lindex $line 0]
266 switch -- $token dir {
267 # original command
268 } 200 {
269 # command successful
270 } 150 {
271 # opening data connection
272 } total {
273 # directory header
274 } 226 {
275 # transfer complete, succeeded!
276 return
277 } ftp>* {
278 # next prompt, failed!
279 return
280 } . {
281 # unreadable
282 } default {
283 # either file or directory
284 set name [getname $line]
285 set type [string index $line 0]
286 getentry $name $type $transfer
287 }
288 }
289}
290
291proc settype {t} {
292 global current_type
293
294 send "type $t\r"
295 set current_type $t
296 expect "200*ftp>*"
297}
298
299proc final_msg {} {
300 # write over the previous prompt with our message
301 send_user "\rQuit ftp or cd to another directory and press ~g, ~p, or ~l\n"
302 # and then reprompt
303 send_user "ftp> "
304}
305
306if {[file readable ~/.rftprc]} {source ~/.rftprc}
307set first_time 1
308
309if {$argc>1} {
310 send_user "usage: rftp [host]"
311 exit
312}
313
314send_user "Once logged in, cd to the directory to be transferred and press:\n"
315send_user "~p to put the current directory from the local to the remote host\n"
316send_user "~g to get the current directory from the remote host to the local host\n"
317send_user "~l to list the current directory from the remote host\n"
318
319if {$argc==0} {spawn ftp} else {spawn ftp $argv}
320interact -echo ~g {
321 if {$first_time} {
322 set first_time 0
323 settype $default_type
324 }
325 getcurdirectory 1
326 final_msg
327} -echo ~p {
328 if {$first_time} {
329 set first_time 0
330 settype $default_type
331 }
332 putcurdirectory
333 final_msg
334} -echo ~l {
335 getcurdirectory 0
336 final_msg
337}