Upload Tizen:Base source
[external/bash.git] / examples / scripts.v2 / frcp
1 #! /bin/bash
2 #
3 # original from:
4 #
5 # @(#) frcp.ksh 2.2 93/11/14
6 # 92/06/29 john h. dubois iii (john@armory.com)
7 # 92/10/14 Cleaned up, improved, added -d and -r options
8 # 92/11/11 Made work with a dest of '.'
9 # 93/07/09 Added -l and -n options, & login as anonymous if no .netrc entry
10 # 93/11/14 Use either passwd or password in .netrc, since ftp does.
11 #
12 # conversion to bash v2 syntax by Chet Ramey
13 #
14 # frcp: ftp front end with rcp-like syntax.
15 # Note: requires any machine names given to be listed with
16 #       user and password in .netrc.  If not, anonymous FTP is
17 #       done.
18 #
19 # full path to ftp binary
20 if [ -x /usr/bin/ftp ]; then
21         FTP=/usr/bin/ftp;
22 elif [ -x /usr/ucb/ftp ]; then
23         FTP=/usr/ucb/ftp
24 else
25         FTP=ftp
26 fi
27
28 istrue()
29 {
30         test 0 -ne "$1"
31 }
32 isfalse()
33 {
34         test 0 -eq "$1"
35 }
36
37 # For each filename given, put the filename in filename[n]
38 # and the machine it is on in machine[n].
39 function SplitNames {
40     typeset file
41     typeset -i i=1
42
43     unset filename[*] machine[*]
44     for file; do
45         case "$file" in
46         *:*) machine[i]=${file%%:*} ;;
47         *)   machine[i]=$LocalMach ;;
48         esac
49         filename[i]=${file#*:}
50         let i+=1
51     done
52 }
53
54 function verboseprint {
55     echo "$@"
56     echo "$@" 1>&2
57 }
58
59 function MakeDir {
60     OFS=$IFS
61     local IFS=/ dir component
62
63     case "$1" in
64     /*) ;;
65      *) dir=.
66     esac
67     set -- $1
68     IFS=$OFS
69     for component; do
70         dir=$dir/$component
71         if [ ! -d "$dir" ]; then
72             if mkdir "$dir"; then :; else
73                 echo "Could not make directory $dir." >&2
74                 return 1
75             fi
76         fi
77     done
78     return 0
79 }
80
81 lastisdot ()
82 {
83         case "$1" in
84         */.|*/..)       return 0;;
85         *)      return 1;;
86         esac
87 }
88
89 # CopyFiles: issue ftp(TC) commands to copy files.
90 # Usage: CopyFiles [sourcemachine:]sourcepath ... [destmachine:]destpath
91 # Global vars:
92 # Uses LocalMach (should be name of local machine)
93 # Sets global arrs machine[]/filename[]
94 function CopyFiles {
95     unset machine[*] filename[*]
96
97     SplitNames "$@"     # split names into filename[1..n] and machine[1..n]
98
99     local DestMach=${machine[$#]}       # Machine to copy files to
100     local DestPath=${filename[$#]}      # Destination file/dir
101
102     unset machine[$#] filename[$#]
103
104     [ -z "$DestPath" ] && DestPath=.    # dest was given as machine:
105
106     # Try to determine if destination should be a directory
107     # so that it can be forced to be a directory.
108
109     case "$DestPath" in
110     */) ;;      # don't add / if trailing / already present
111     *)  if [ $# -gt 2 ] || # if more than two args given, last must be a dir
112             # If dest in on local machine, check whether it is a directory
113            [ $DestMach = $LocalMach ] && [ -d "$DestPath" ] || 
114             # If dest ends with . or .., it is a directory
115            lastisdot "$DestPath"
116         then
117                 DestPath=$DestPath/
118         fi ;;
119     esac
120
121     # If one of the above tests made us think dest is a directory,
122     # but it isn't, complain
123     case "$DestPath" in
124     */) if [ "$DestMach" = "$LocalMach" ] && [ ! -d "$DestPath" ]; then
125                 echo "Destination is not a directory." 1>&2
126                 exit 1
127         fi ;;
128     esac
129
130     DoCopy "$DestMach" "$DestPath"
131 }
132
133 # Usage: OpenMachine machine-name
134 # Emits login sequence or doesn't, depending on .netrc file and global
135 # variables anon and noanon
136 OpenMachine ()
137 {
138     local machine=$1 netrc=$HOME/.netrc user= password=
139
140     if isfalse $anon && [ -r $netrc ]; then
141         set -- $(gawk '
142         /machine (.* )?'"$machine"'($| )/,/^ *$/ {
143             Fields[$1] = $2
144             if ("passwd" in Fields)
145                 Fields["password"] = Fields["passwd"]
146             if ("login" in Fields && "password" in Fields) {
147                 print Fields["login"] " " Fields["password"]
148                 exit
149             }
150         }
151         ' $netrc )
152         user=$1
153         password=$2
154     fi
155     if [ -z "$password" ]; then
156         if istrue $noanon; then
157             echo "No .netrc entry for machine $machine" 1>&2
158             exit 1
159         fi
160         user=anonymous
161         password=$USER@$LocalMach
162     fi
163     verboseprint open $machine
164     echo user $user "*******" 1>&2
165     echo user $user $password
166 }
167
168 # Usage: DoCopy destination-machine destination-path
169 # Copies the files in global arrs machine[]/filename[] to the given dest
170 # Global vars:
171 # Uses machine[], filename[], LocalMach, check
172 DoCopy ()
173 {
174     local DestMach=$1
175     local DestPath=$2
176     local OpenMach      # Machine that connection is currently open to
177     local OWD=$PWD SourceMach SourceFile
178     local FileName
179     typeset -i i=1
180
181     while [ $i -le ${#machine[*]} ]; do
182         istrue $check && verboseprint "runique"
183
184         SourceMach=${machine[i]}
185         SourceFile=${filename[i]}
186
187         DestFile=$DestPath
188         # if DestPath is a dir,
189         # add source filename to it without source path
190         case "$DestFile" in
191         */)     DestFile=$DestFile${SourceFile##*/} ;;
192         esac
193
194         if [ $SourceMach = $LocalMach ]; then
195             if [ $DestMach != "$OpenMach" ]; then
196                 OpenMachine $DestMach
197                 OpenMach=$DestMach
198             fi
199             verboseprint put $SourceFile $DestFile
200         elif [ $DestMach = $LocalMach ]; then
201             if istrue $check && [ -f "$DestFile" ]; then
202                 echo "$DestFile already exists." 1>&2
203                 continue
204             fi
205             # If destination is on local machine,
206             # the dest will be a full dir/filename
207             if istrue $createdirs; then
208                 MakeDir "${DestFile%/*}" || continue
209             fi
210             if [ $SourceMach != "$OpenMach" ]; then
211                 OpenMachine $SourceMach
212                 OpenMach=$SourceMach
213             fi
214             # If source filename has wildcards ([, ], *, ?) do an mget
215             case "$SourceFile" in
216             \[*\]|*\**|*\?*)
217                 verboseprint lcd "$DestFile"
218                 verboseprint mget "$SourceFile"
219                 verboseprint lcd $OWD ;;
220             *)  verboseprint get "$SourceFile" "$DestFile" ;;
221             esac
222         else
223             echo "Neither source machine \"$SourceMach\" "\
224 "nor destination machine \"$DestMach\" is local." 1>&2
225         fi
226         let i+=1
227     done
228 }
229
230 # Start of main program
231 name=${0##*/}
232
233 if [ "$1" = -h ]; then
234     echo \
235 "$name: do ftp transfers using rcp-style parameters.
236 Usage: $name <source> <destpath>   or   $name <source> [<source> ...] <destdir>
237 At least one of <source> and <destpath> must be the local system.
238 A remote filename is given as machinename:filename
239 If remote filenames contain wildcards, they will be globbed on the remote
240 machine.  Make sure they are quoted when $name is invoked.
241 If the invoking user's .netrc file (see ftp(TC)) contains an entry for the
242 remote system with a login and password supplied, $name will log in using
243 the given login and password.  If not, $name will login in as user
244 anonymous and with the user@localsystem as the password.
245 Options:
246 -c: check: do not overwrite files.
247 -d: create directories as needed.
248 -f: force: overwrite files (default).
249 -h: print this help.
250 -l: fail if there is no entry with login and password for the remote system,
251     instead of logging in as anonymous.
252 -n: log in as anonymous even if there is an entry for the remote system in
253     the user's .netrc file.
254 -r: read source/dest filename pairs from the standard input,
255     one pair per line, and copy files accordingly."
256     exit 0
257 fi
258
259 typeset -i check=0 createdirs=0 readinput=0 anon=0 noanon=0
260
261 while getopts :cdflnr Option
262 do
263     case "$Option" in
264     c) check=1;;
265     d) createdirs=1;;
266     f) check=0;;
267     l) noanon=1;;
268     n) anon=1;;
269     r) readinput=1;;
270     \?) echo "$OPTARG: invalid option."; exit 1;;
271     esac
272 done
273
274 shift $((OPTIND-1))
275
276 LocalMach=`hostname` 
277
278 if istrue $readinput; then
279     while read line; do
280         CopyFiles $line
281     done | $FTP -nv
282 else
283     if [ $# -lt 2 ]; then
284         echo "$name: Not enough arguments.  Use -h for help." 1>&2
285         exit
286     fi
287     CopyFiles "$@" | $FTP -nv
288 fi