Fixed filan -s, added -S
[socat.git] / ftp.sh
bloba7474d2522981715e28ed44a32664cc242f0c543
1 #! /bin/sh
2 # source: ftp.sh
3 # Copyright Gerhard Rieger and contributors (see file CHANGES)
4 # Published under the GNU General Public License V.2, see file COPYING
6 # example how to write a shell script that communicates with stdio on the front
7 # end and with a socat address on the back end
9 # usage:
10 # ftp.sh [opts] server directory/ # show directory contents on stdout
11 # ftp.sh [opts] server file # print file contents to stdout
12 # opts:
13 # -socks socksserver # use given socks server, port 1080
14 # -proxy proxyserver # use given proxy server, port 8080
15 # # must be http proxy that accepts CONNECT
16 # # method to ports 21 and >=1024
17 # -user username # default: "ftp"
18 # -passwd password # default: "anonymous@domain.org"
19 # -t # shell script trace+debug
20 # -d # debug on control connection (use up to 4 times)
21 # -D # debug on data connection (use up to 4 times)
22 # -b # block size for data connection
23 # -v # verbose
24 # -l* # socat logging options
25 # example:
26 # ftp.sh -v -d -d -D -D -D -b 65536 -proxy proxy ftp.ftp.org /README >README
28 user="ftp"
29 passwd="anonymous@domain.org"
30 #method="socks4:socks" # socks4 is address spec, socks is socks server name
31 method=tcp
32 addropts=
34 # socat options
35 SO1=
36 SO2=
38 while :; do
39 case "$1" in
40 -socks|-socks4) shift;
41 case "$1" in
42 *:*) method="socks4:${1%%:*}"; addropts="socksport=${1#*:}" ;;
43 *) method="socks4:$1" ;;
44 esac ;;
45 -socks4a) shift;
46 case "$1" in
47 *:*) method="socks4a:${1%%:*}"; addropts="socksport=${1#*:}" ;;
48 *) method="socks4a:$1" ;;
49 esac ;;
50 -proxy) shift;
51 case "$1" in
52 *:*) method="proxy:${1%%:*}"; addropts="proxyport=${1#*:}" ;;
53 *) method="proxy:$1" ;;
54 esac ;;
55 -user) shift; user="$1" ;;
56 -passwd) shift; passwd="$1" ;;
57 -t) set -vx ;;
58 -d) SO1="$SO1 -d" ;;
59 -D) SO2="$SO2 -d" ;;
60 -b) SO2="$SO2 -b $2"; shift ;;
61 -v) SO1="$SO1 -v" ;;
62 -l*) SO1="$SO1 $1"; SO2="$SO2 $1" ;;
63 -*) echo "unknown option \"$1\"" >&2; exit 1;;
64 *) break ;;
65 esac
66 shift
67 done
68 export SO2
70 server="$1"
71 dir="$2"
73 echo "addr=$method:$server:21,$addropts"; exit
75 ### this is the central part to establish communication with socat ###
76 ### copy these lines to make new communication shell scripts
77 TMPDIR=$(if [ -x /bin/mktemp ]; then
78 /bin/mktemp -d /tmp/$USER/FTPSH.XXXXXX
79 else
80 (umask 077; d=/tmp/$USER/FTPSH.$$; mkdir $d; echo $d)
81 fi)
82 TO="$TMPDIR/to"; FROM="$TMPDIR/from"
83 socat $SO1 fifo:$TO,nonblock,ignoreeof!!fifo:$FROM $method:$server:21,$addropts &
84 S1=$!
85 while ! [ -p "$TO" -a -p "$FROM" ]; do sleep 1; done
86 exec 4>$TMPDIR/to 3<$TMPDIR/from
87 trap "S1=" 17
88 #trap "echo cleaning up...>&2; rm -r $TMPDIR; [ -n "$S1" ] && kill $S1" 0 3
89 trap "rm -r $TMPDIR" 0 3
90 ### here the central part ends
93 # this function waits for a complete server message, checks if its status
94 # is in the permitted range (terminates session if not), and returns.
95 ftp_chat () {
96 local cmd="$1"
97 local errlevel="$2"; [ -z "$errlevel" ] && errlevel=300
98 if [ -n "$cmd" ]; then echo "$cmd" >&4; fi
99 while read status message <&3;
100 ( case "$status" in [0-9][0-9][0-9]-*) exit 0;; [0-9][0-9][0-9]*) exit 1;; *) exit 1;; esac )
101 do :; done
102 #echo "got \"$status $message\"" >&2
103 if [ -z "$status" ]; then echo ftp data connection failed >&2; exit; fi
104 if [ "$status" -ge "$errlevel" ]; then
105 echo $message >&2
106 echo "QUIT" >&4; exit 1
108 set +vx
112 # wait for server greeting
113 ftp_chat
115 ftp_chat "USER $user" 400
117 ftp_chat "PASS $passwd"
119 #ftp_chat "CWD $dir"
121 case "$dir" in
122 */) ftp_chat "TYPE A" ;;
123 *) ftp_chat "TYPE I" ;;
124 esac
126 echo "PASV" >&4; read status message <&3
127 info=$(expr "$message" : '.*[^0-9]\([0-9]*,[0-9]*,[0-9]*,[0-9]*,[0-9]*,[0-9]*\).*')
128 echo $info |tr ',' ' ' |(read i1 i2 i3 i4 p1 p2
130 addr=$i1.$i2.$i3.$i4
131 port=$(echo "256*$p1+$p2" |bc)
132 #echo $addr:$port
134 trap : 20
135 # open data connection and transfer data
136 socat -u $SO2 $method:$server:$port,$addropts -
138 S2=$!
140 case "$dir" in
141 */) ftp_chat "NLST $dir" ;;
142 #*/) ftp_chat "LIST $dir" ;;
143 *) ftp_chat "RETR $dir" ;;
144 esac
145 case "$status" in
146 [45]*) kill $S2;;
147 esac
149 #echo "waiting for process $S2 to terminate" >&2
150 wait $S2
152 ftp_chat
154 ftp_chat "QUIT"
156 #echo "waiting for process $S1 to terminate" >&2
157 wait $S1
158 exit