blob: 3a9930cd78296e6a11be333235dd54482b577cbc [file] [log] [blame]
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +00001/* vi: set sw=4 ts=4: */
2/*
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003 * ftpget
4 *
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +00005 * Mini implementation of FTP to retrieve a remote file.
6 *
7 * Copyright (C) 2002 Jeff Angielski, The PTR Group <jeff@theptrgroup.com>
Denis Vlasenko0beaff82007-09-21 13:16:32 +00008 * Copyright (C) 2002 Glenn McGrath
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +00009 *
10 * Based on wget.c by Chip Rosenthal Covad Communications
11 * <chip@laserlink.net>
12 *
Rob Landley6f037222005-11-08 00:52:31 +000013 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000014 */
15
Denis Vlasenkob6adbf12007-05-26 19:00:18 +000016#include "libbb.h"
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000017
18typedef struct ftp_host_info_s {
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +000019 const char *user;
20 const char *password;
Denis Vlasenko8e9ccba2007-01-11 16:50:23 +000021 struct len_and_sockaddr *lsa;
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000022} ftp_host_info_t;
23
Denis Vlasenko3821fb12007-01-11 16:51:21 +000024static smallint verbose_flag;
25static smallint do_continue;
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000026
Denis Vlasenko562dc242007-01-03 21:55:50 +000027static void ftp_die(const char *msg, const char *remote) ATTRIBUTE_NORETURN;
28static void ftp_die(const char *msg, const char *remote)
29{
30 /* Guard against garbage from remote server */
31 const char *cp = remote;
32 while (*cp >= ' ' && *cp < '\x7f') cp++;
33 bb_error_msg_and_die("unexpected server response%s%s: %.*s",
34 msg ? " to " : "", msg ? msg : "",
35 (int)(cp - remote), remote);
36}
37
38
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000039static int ftpcmd(const char *s1, const char *s2, FILE *stream, char *buf)
40{
Denis Vlasenko562dc242007-01-03 21:55:50 +000041 unsigned n;
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000042 if (verbose_flag) {
Denis Vlasenko3821fb12007-01-11 16:51:21 +000043 bb_error_msg("cmd %s %s", s1, s2);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000044 }
45
46 if (s1) {
47 if (s2) {
Denis Vlasenko562dc242007-01-03 21:55:50 +000048 fprintf(stream, "%s %s\r\n", s1, s2);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000049 } else {
Paul Fox146e83a2005-07-19 21:26:57 +000050 fprintf(stream, "%s\r\n", s1);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000051 }
52 }
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000053 do {
Glenn L McGrath5ec58282004-05-04 10:43:34 +000054 char *buf_ptr;
55
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000056 if (fgets(buf, 510, stream) == NULL) {
Denis Vlasenko13858992006-10-08 12:49:22 +000057 bb_perror_msg_and_die("fgets");
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000058 }
Glenn L McGrath5ec58282004-05-04 10:43:34 +000059 buf_ptr = strstr(buf, "\r\n");
60 if (buf_ptr) {
61 *buf_ptr = '\0';
62 }
Denis Vlasenko13858992006-10-08 12:49:22 +000063 } while (!isdigit(buf[0]) || buf[3] != ' ');
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000064
Denis Vlasenko562dc242007-01-03 21:55:50 +000065 buf[3] = '\0';
66 n = xatou(buf);
67 buf[3] = ' ';
68 return n;
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000069}
70
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000071static FILE *ftp_login(ftp_host_info_t *server)
72{
73 FILE *control_stream;
74 char buf[512];
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000075
76 /* Connect to the command socket */
Denis Vlasenko8e9ccba2007-01-11 16:50:23 +000077 control_stream = fdopen(xconnect_stream(server->lsa), "r+");
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000078 if (control_stream == NULL) {
Denis Vlasenko8e9ccba2007-01-11 16:50:23 +000079 /* fdopen failed - extremely unlikely */
Denis Vlasenko562dc242007-01-03 21:55:50 +000080 bb_perror_nomsg_and_die();
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000081 }
82
83 if (ftpcmd(NULL, NULL, control_stream, buf) != 220) {
Denis Vlasenko562dc242007-01-03 21:55:50 +000084 ftp_die(NULL, buf);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000085 }
86
87 /* Login to the server */
Denis Vlasenko562dc242007-01-03 21:55:50 +000088 switch (ftpcmd("USER", server->user, control_stream, buf)) {
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000089 case 230:
90 break;
91 case 331:
Denis Vlasenko562dc242007-01-03 21:55:50 +000092 if (ftpcmd("PASS", server->password, control_stream, buf) != 230) {
93 ftp_die("PASS", buf);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000094 }
95 break;
96 default:
Denis Vlasenko562dc242007-01-03 21:55:50 +000097 ftp_die("USER", buf);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000098 }
99
100 ftpcmd("TYPE I", NULL, control_stream, buf);
101
Denis Vlasenko079f8af2006-11-27 16:49:31 +0000102 return control_stream;
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000103}
104
Denis Vlasenko6c615a62008-03-28 22:11:49 +0000105static int xconnect_ftpdata(ftp_host_info_t *server, char *buf)
106{
107 char *buf_ptr;
108 unsigned port_num;
109
110 /* Response is "NNN garbageN1,N2,N3,N4,P1,P2[)garbage]
111 * Server's IP is N1.N2.N3.N4 (we ignore it)
112 * Server's port for data connection is P1*256+P2 */
113 buf_ptr = strrchr(buf, ')');
114 if (buf_ptr) *buf_ptr = '\0';
115
116 buf_ptr = strrchr(buf, ',');
117 *buf_ptr = '\0';
118 port_num = xatoul_range(buf_ptr + 1, 0, 255);
119
120 buf_ptr = strrchr(buf, ',');
121 *buf_ptr = '\0';
122 port_num += xatoul_range(buf_ptr + 1, 0, 255) * 256;
123
124 set_nport(server->lsa, htons(port_num));
125 return xconnect_stream(server->lsa);
126}
127
Rob Landleyb1c3fbc2006-05-04 19:52:28 +0000128#if !ENABLE_FTPGET
Denis Vlasenko7039a662006-10-08 17:54:47 +0000129int ftp_receive(ftp_host_info_t *server, FILE *control_stream,
130 const char *local_path, char *server_path);
Rob Landleyb1c3fbc2006-05-04 19:52:28 +0000131#else
Denis Vlasenko7039a662006-10-08 17:54:47 +0000132static
133int ftp_receive(ftp_host_info_t *server, FILE *control_stream,
Eric Andersen04d055f2003-11-03 21:20:18 +0000134 const char *local_path, char *server_path)
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000135{
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000136 char buf[512];
Denis Vlasenko714701c2006-12-22 00:21:07 +0000137/* I think 'filesize' usage here is bogus. Let's see... */
138 //off_t filesize = -1;
139#define filesize ((off_t)-1)
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000140 int fd_data;
Glenn L McGrath236e93d2003-12-20 05:43:34 +0000141 int fd_local = -1;
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000142 off_t beg_range = 0;
143
Denis Vlasenko6c615a62008-03-28 22:11:49 +0000144/*
145TODO: PASV command will not work for IPv6. RFC2428 describes
146IPv6-capable "extended PASV" - EPSV.
147
148"EPSV [protocol]" asks server to bind to and listen on a data port
149in specified protocol. Protocol is 1 for IPv4, 2 for IPv6.
150If not specified, defaults to "same as used for control connection".
151If server understood you, it should answer "229 <some text>(|||port|)"
152where "|" are literal pipe chars and "port" is ASCII decimal port#.
153
154There is also an IPv6-capable replacement for PORT (EPRT),
155but we don't need that.
156
157TODO: fold in sending of PASV/EPSV and parsing of response into
158xconnect_ftpdata(). (Also, need to stop ignoring IP address in PASV
159response).
160*/
161
162 /* connect to the data socket */
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000163 if (ftpcmd("PASV", NULL, control_stream, buf) != 227) {
Denis Vlasenko562dc242007-01-03 21:55:50 +0000164 ftp_die("PASV", buf);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000165 }
Eric Andersen04d055f2003-11-03 21:20:18 +0000166 fd_data = xconnect_ftpdata(server, buf);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000167
Denis Vlasenko562dc242007-01-03 21:55:50 +0000168 if (ftpcmd("SIZE", server_path, control_stream, buf) == 213) {
Denis Vlasenko714701c2006-12-22 00:21:07 +0000169 //filesize = BB_STRTOOFF(buf + 4, NULL, 10);
170 //if (errno || filesize < 0)
Denis Vlasenko562dc242007-01-03 21:55:50 +0000171 // ftp_die("SIZE", buf);
Rob Landleybc059bc2006-01-10 06:36:00 +0000172 } else {
Rob Landleybc059bc2006-01-10 06:36:00 +0000173 do_continue = 0;
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000174 }
175
Denis Vlasenko9f739442006-12-16 23:49:13 +0000176 if (LONE_DASH(local_path)) {
Eric Andersen70060d22004-03-27 10:02:48 +0000177 fd_local = STDOUT_FILENO;
Glenn L McGrath236e93d2003-12-20 05:43:34 +0000178 do_continue = 0;
179 }
180
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000181 if (do_continue) {
182 struct stat sbuf;
Denis Vlasenko6c615a62008-03-28 22:11:49 +0000183 /* lstat would be wrong here! */
184 if (stat(local_path, &sbuf) < 0) {
185 bb_perror_msg_and_die("stat");
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000186 }
187 if (sbuf.st_size > 0) {
188 beg_range = sbuf.st_size;
189 } else {
190 do_continue = 0;
191 }
192 }
193
194 if (do_continue) {
Denis Vlasenkocf30cc82006-11-24 14:53:18 +0000195 sprintf(buf, "REST %"OFF_FMT"d", beg_range);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000196 if (ftpcmd(buf, NULL, control_stream, buf) != 350) {
197 do_continue = 0;
198 } else {
Denis Vlasenko714701c2006-12-22 00:21:07 +0000199 //if (filesize != -1)
200 // filesize -= beg_range;
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000201 }
202 }
203
Denis Vlasenko562dc242007-01-03 21:55:50 +0000204 if (ftpcmd("RETR", server_path, control_stream, buf) > 150) {
205 ftp_die("RETR", buf);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000206 }
207
Denis Vlasenko6c615a62008-03-28 22:11:49 +0000208 /* make local _after_ we know that remote file exists */
Glenn L McGrath236e93d2003-12-20 05:43:34 +0000209 if (fd_local == -1) {
Denis Vlasenko6c615a62008-03-28 22:11:49 +0000210 fd_local = xopen(local_path,
211 do_continue ? (O_APPEND | O_WRONLY)
212 : (O_CREAT | O_TRUNC | O_WRONLY)
213 );
Glenn L McGrath1643f412002-12-18 02:47:40 +0000214 }
215
Denis Vlasenko6c615a62008-03-28 22:11:49 +0000216// TODO: merge tail of ftp_receive and ftp_send starting from here
217
218 /* copy the file */
219 if (filesize != -1) { // NEVER HAPPENS, filesize is always -1
Denis Vlasenko714701c2006-12-22 00:21:07 +0000220 if (bb_copyfd_size(fd_data, fd_local, filesize) == -1)
221 return EXIT_FAILURE;
Rob Landleybc059bc2006-01-10 06:36:00 +0000222 } else {
Denis Vlasenko6c615a62008-03-28 22:11:49 +0000223 if (bb_copyfd_eof(fd_data, fd_local) == -1) {
224 /* error msg is already printed by bb_copyfd_eof */
Denis Vlasenko714701c2006-12-22 00:21:07 +0000225 return EXIT_FAILURE;
Denis Vlasenko6c615a62008-03-28 22:11:49 +0000226 }
Glenn L McGrath25fe94f2002-12-13 08:20:44 +0000227 }
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000228
229 /* close it all down */
230 close(fd_data);
231 if (ftpcmd(NULL, NULL, control_stream, buf) != 226) {
Denis Vlasenko562dc242007-01-03 21:55:50 +0000232 ftp_die(NULL, buf);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000233 }
234 ftpcmd("QUIT", NULL, control_stream, buf);
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000235
Denis Vlasenko079f8af2006-11-27 16:49:31 +0000236 return EXIT_SUCCESS;
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000237}
238#endif
239
Rob Landleyb1c3fbc2006-05-04 19:52:28 +0000240#if !ENABLE_FTPPUT
Denis Vlasenko7039a662006-10-08 17:54:47 +0000241int ftp_send(ftp_host_info_t *server, FILE *control_stream,
242 const char *server_path, char *local_path);
Rob Landleyb1c3fbc2006-05-04 19:52:28 +0000243#else
Denis Vlasenko7039a662006-10-08 17:54:47 +0000244static
245int ftp_send(ftp_host_info_t *server, FILE *control_stream,
Eric Andersen04d055f2003-11-03 21:20:18 +0000246 const char *server_path, char *local_path)
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000247{
248 struct stat sbuf;
249 char buf[512];
250 int fd_data;
251 int fd_local;
252 int response;
253
Denis Vlasenko6c615a62008-03-28 22:11:49 +0000254 /* connect to the data socket */
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000255 if (ftpcmd("PASV", NULL, control_stream, buf) != 227) {
Denis Vlasenko562dc242007-01-03 21:55:50 +0000256 ftp_die("PASV", buf);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000257 }
Eric Andersen04d055f2003-11-03 21:20:18 +0000258 fd_data = xconnect_ftpdata(server, buf);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000259
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000260 /* get the local file */
Denis Vlasenko9f739442006-12-16 23:49:13 +0000261 fd_local = STDIN_FILENO;
262 if (NOT_LONE_DASH(local_path)) {
Rob Landleyd921b2e2006-08-03 15:41:12 +0000263 fd_local = xopen(local_path, O_RDONLY);
Glenn L McGrath236e93d2003-12-20 05:43:34 +0000264 fstat(fd_local, &sbuf);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000265
Denis Vlasenko6c615a62008-03-28 22:11:49 +0000266// TODO: do we really need to send ALLO? It's ancient...
267// Doesn't it break "ftpput .. .. fifo" too?
268
Denis Vlasenko562dc242007-01-03 21:55:50 +0000269 sprintf(buf, "ALLO %"OFF_FMT"u", sbuf.st_size);
Glenn L McGrath236e93d2003-12-20 05:43:34 +0000270 response = ftpcmd(buf, NULL, control_stream, buf);
271 switch (response) {
272 case 200:
273 case 202:
274 break;
275 default:
Denis Vlasenko6c615a62008-03-28 22:11:49 +0000276 close(fd_local); // TODO: why bother?
Denis Vlasenko562dc242007-01-03 21:55:50 +0000277 ftp_die("ALLO", buf);
Glenn L McGrath236e93d2003-12-20 05:43:34 +0000278 break;
279 }
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000280 }
Denis Vlasenko562dc242007-01-03 21:55:50 +0000281 response = ftpcmd("STOR", server_path, control_stream, buf);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000282 switch (response) {
283 case 125:
284 case 150:
285 break;
286 default:
Denis Vlasenko6c615a62008-03-28 22:11:49 +0000287 close(fd_local); // TODO: why bother?
Denis Vlasenko562dc242007-01-03 21:55:50 +0000288 ftp_die("STOR", buf);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000289 }
290
291 /* transfer the file */
Glenn L McGrath7ffe1332003-11-21 22:24:57 +0000292 if (bb_copyfd_eof(fd_local, fd_data) == -1) {
Denis Vlasenko6c615a62008-03-28 22:11:49 +0000293 /* error msg is already printed by bb_copyfd_eof */
294 return EXIT_FAILURE;
Glenn L McGrath25fe94f2002-12-13 08:20:44 +0000295 }
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000296
297 /* close it all down */
298 close(fd_data);
299 if (ftpcmd(NULL, NULL, control_stream, buf) != 226) {
Denis Vlasenko562dc242007-01-03 21:55:50 +0000300 ftp_die("close", buf);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000301 }
302 ftpcmd("QUIT", NULL, control_stream, buf);
303
Denis Vlasenko079f8af2006-11-27 16:49:31 +0000304 return EXIT_SUCCESS;
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000305}
306#endif
307
Glenn L McGrathb51eb262003-12-19 10:37:52 +0000308#define FTPGETPUT_OPT_CONTINUE 1
309#define FTPGETPUT_OPT_VERBOSE 2
310#define FTPGETPUT_OPT_USER 4
311#define FTPGETPUT_OPT_PASSWORD 8
312#define FTPGETPUT_OPT_PORT 16
313
Bernhard Reutner-Fischer01d23ad2006-05-26 20:19:22 +0000314#if ENABLE_FEATURE_FTPGETPUT_LONG_OPTIONS
Denis Vlasenko6ca409e2007-08-12 20:58:27 +0000315static const char ftpgetput_longopts[] ALIGN1 =
Denis Vlasenkobdc88fd2007-07-23 17:14:14 +0000316 "continue\0" Required_argument "c"
317 "verbose\0" No_argument "v"
318 "username\0" Required_argument "u"
319 "password\0" Required_argument "p"
320 "port\0" Required_argument "P"
Denis Vlasenko990d0f62007-07-24 15:54:42 +0000321 ;
Bernhard Reutner-Fischer01d23ad2006-05-26 20:19:22 +0000322#endif
Glenn L McGrathb51eb262003-12-19 10:37:52 +0000323
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +0000324int ftpgetput_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
Denis Vlasenko68404f12008-03-17 09:00:54 +0000325int ftpgetput_main(int argc ATTRIBUTE_UNUSED, char **argv)
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000326{
327 /* content-length of the file */
Denis Vlasenko67b23e62006-10-03 21:00:06 +0000328 unsigned opt;
Denis Vlasenko562dc242007-01-03 21:55:50 +0000329 const char *port = "ftp";
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000330 /* socket to ftp server */
331 FILE *control_stream;
Denis Vlasenko562dc242007-01-03 21:55:50 +0000332 /* continue previous transfer (-c) */
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000333 ftp_host_info_t *server;
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000334
Denis Vlasenko562dc242007-01-03 21:55:50 +0000335#if ENABLE_FTPPUT && !ENABLE_FTPGET
336# define ftp_action ftp_send
337#elif ENABLE_FTPGET && !ENABLE_FTPPUT
338# define ftp_action ftp_receive
339#else
340 int (*ftp_action)(ftp_host_info_t *, FILE *, const char *, char *) = ftp_send;
Glenn L McGrath266c1f52003-12-20 03:19:27 +0000341 /* Check to see if the command is ftpget or ftput */
Denis Vlasenko562dc242007-01-03 21:55:50 +0000342 if (applet_name[3] == 'g') {
Bernhard Reutner-Fischere0387a62006-06-07 13:31:59 +0000343 ftp_action = ftp_receive;
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000344 }
Denis Vlasenko562dc242007-01-03 21:55:50 +0000345#endif
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000346
347 /* Set default values */
Denis Vlasenko4fa5e8b2007-01-11 22:39:25 +0000348 server = xmalloc(sizeof(*server));
Glenn L McGrath266c1f52003-12-20 03:19:27 +0000349 server->user = "anonymous";
350 server->password = "busybox@";
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000351
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000352 /*
353 * Decipher the command line
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000354 */
Denis Vlasenkoc61852a2006-11-29 11:09:43 +0000355#if ENABLE_FEATURE_FTPGETPUT_LONG_OPTIONS
Denis Vlasenkobdc88fd2007-07-23 17:14:14 +0000356 applet_long_options = ftpgetput_longopts;
Denis Vlasenkoc61852a2006-11-29 11:09:43 +0000357#endif
Denis Vlasenko562dc242007-01-03 21:55:50 +0000358 opt_complementary = "=3"; /* must have 3 params */
Denis Vlasenkofe7cd642007-08-18 15:32:12 +0000359 opt = getopt32(argv, "cvu:p:P:", &server->user, &server->password, &port);
Denis Vlasenko562dc242007-01-03 21:55:50 +0000360 argv += optind;
Glenn L McGrath236e93d2003-12-20 05:43:34 +0000361
362 /* Process the non-option command line arguments */
Glenn L McGrathb51eb262003-12-19 10:37:52 +0000363 if (opt & FTPGETPUT_OPT_CONTINUE) {
364 do_continue = 1;
365 }
366 if (opt & FTPGETPUT_OPT_VERBOSE) {
367 verbose_flag = 1;
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000368 }
369
Eric Andersen04d055f2003-11-03 21:20:18 +0000370 /* We want to do exactly _one_ DNS lookup, since some
371 * sites (i.e. ftp.us.debian.org) use round-robin DNS
372 * and we want to connect to only one IP... */
Denis Vlasenko42823d52007-02-04 02:39:08 +0000373 server->lsa = xhost2sockaddr(argv[0], bb_lookup_port(port, "tcp", 21));
Eric Andersen04d055f2003-11-03 21:20:18 +0000374 if (verbose_flag) {
Denis Vlasenko85629f02007-01-22 09:36:41 +0000375 printf("Connecting to %s (%s)\n", argv[0],
Bernhard Reutner-Fischer8c69afd2008-01-29 10:33:34 +0000376 xmalloc_sockaddr2dotted(&server->lsa->u.sa));
Eric Andersen04d055f2003-11-03 21:20:18 +0000377 }
378
379 /* Connect/Setup/Configure the FTP session */
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000380 control_stream = ftp_login(server);
381
Denis Vlasenko562dc242007-01-03 21:55:50 +0000382 return ftp_action(server, control_stream, argv[1], argv[2]);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000383}