blob: dad1c9947e71e7cb12d6e04a396b9eebbe7dc161 [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>
Glenn L McGrathc6992fe2004-04-25 05:11:19 +00008 * Copyright (C) 2002 Glenn McGrath <bug1@iinet.net.au>
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
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000016#include "busybox.h"
Rob Landleyd921b2e2006-08-03 15:41:12 +000017#include <getopt.h>
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000018
19typedef struct ftp_host_info_s {
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +000020 const char *user;
21 const char *password;
Denis Vlasenko8e9ccba2007-01-11 16:50:23 +000022 struct len_and_sockaddr *lsa;
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000023} ftp_host_info_t;
24
Denis Vlasenko3821fb12007-01-11 16:51:21 +000025static smallint verbose_flag;
26static smallint do_continue;
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000027
Denis Vlasenko562dc242007-01-03 21:55:50 +000028static void ftp_die(const char *msg, const char *remote) ATTRIBUTE_NORETURN;
29static void ftp_die(const char *msg, const char *remote)
30{
31 /* Guard against garbage from remote server */
32 const char *cp = remote;
33 while (*cp >= ' ' && *cp < '\x7f') cp++;
34 bb_error_msg_and_die("unexpected server response%s%s: %.*s",
35 msg ? " to " : "", msg ? msg : "",
36 (int)(cp - remote), remote);
37}
38
39
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000040static int ftpcmd(const char *s1, const char *s2, FILE *stream, char *buf)
41{
Denis Vlasenko562dc242007-01-03 21:55:50 +000042 unsigned n;
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000043 if (verbose_flag) {
Denis Vlasenko3821fb12007-01-11 16:51:21 +000044 bb_error_msg("cmd %s %s", s1, s2);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000045 }
46
47 if (s1) {
48 if (s2) {
Denis Vlasenko562dc242007-01-03 21:55:50 +000049 fprintf(stream, "%s %s\r\n", s1, s2);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000050 } else {
Paul Fox146e83a2005-07-19 21:26:57 +000051 fprintf(stream, "%s\r\n", s1);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000052 }
53 }
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000054 do {
Glenn L McGrath5ec58282004-05-04 10:43:34 +000055 char *buf_ptr;
56
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000057 if (fgets(buf, 510, stream) == NULL) {
Denis Vlasenko13858992006-10-08 12:49:22 +000058 bb_perror_msg_and_die("fgets");
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000059 }
Glenn L McGrath5ec58282004-05-04 10:43:34 +000060 buf_ptr = strstr(buf, "\r\n");
61 if (buf_ptr) {
62 *buf_ptr = '\0';
63 }
Denis Vlasenko13858992006-10-08 12:49:22 +000064 } while (!isdigit(buf[0]) || buf[3] != ' ');
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000065
Denis Vlasenko562dc242007-01-03 21:55:50 +000066 buf[3] = '\0';
67 n = xatou(buf);
68 buf[3] = ' ';
69 return n;
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000070}
71
Denis Vlasenko562dc242007-01-03 21:55:50 +000072static int xconnect_ftpdata(ftp_host_info_t *server, char *buf)
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000073{
74 char *buf_ptr;
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000075 unsigned short port_num;
76
Denis Vlasenko562dc242007-01-03 21:55:50 +000077 /* Response is "NNN garbageN1,N2,N3,N4,P1,P2[)garbage]
78 * Server's IP is N1.N2.N3.N4 (we ignore it)
79 * Server's port for data connection is P1*256+P2 */
80 buf_ptr = strrchr(buf, ')');
81 if (buf_ptr) *buf_ptr = '\0';
82
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000083 buf_ptr = strrchr(buf, ',');
84 *buf_ptr = '\0';
Denis Vlasenko13858992006-10-08 12:49:22 +000085 port_num = xatoul_range(buf_ptr + 1, 0, 255);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000086
87 buf_ptr = strrchr(buf, ',');
88 *buf_ptr = '\0';
Denis Vlasenko13858992006-10-08 12:49:22 +000089 port_num += xatoul_range(buf_ptr + 1, 0, 255) * 256;
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000090
Denis Vlasenko5d687242007-01-12 20:59:31 +000091 set_nport(server->lsa, htons(port_num));
Denis Vlasenko8e9ccba2007-01-11 16:50:23 +000092 return xconnect_stream(server->lsa);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000093}
94
95static FILE *ftp_login(ftp_host_info_t *server)
96{
97 FILE *control_stream;
98 char buf[512];
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000099
100 /* Connect to the command socket */
Denis Vlasenko8e9ccba2007-01-11 16:50:23 +0000101 control_stream = fdopen(xconnect_stream(server->lsa), "r+");
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000102 if (control_stream == NULL) {
Denis Vlasenko8e9ccba2007-01-11 16:50:23 +0000103 /* fdopen failed - extremely unlikely */
Denis Vlasenko562dc242007-01-03 21:55:50 +0000104 bb_perror_nomsg_and_die();
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000105 }
106
107 if (ftpcmd(NULL, NULL, control_stream, buf) != 220) {
Denis Vlasenko562dc242007-01-03 21:55:50 +0000108 ftp_die(NULL, buf);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000109 }
110
111 /* Login to the server */
Denis Vlasenko562dc242007-01-03 21:55:50 +0000112 switch (ftpcmd("USER", server->user, control_stream, buf)) {
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000113 case 230:
114 break;
115 case 331:
Denis Vlasenko562dc242007-01-03 21:55:50 +0000116 if (ftpcmd("PASS", server->password, control_stream, buf) != 230) {
117 ftp_die("PASS", buf);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000118 }
119 break;
120 default:
Denis Vlasenko562dc242007-01-03 21:55:50 +0000121 ftp_die("USER", buf);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000122 }
123
124 ftpcmd("TYPE I", NULL, control_stream, buf);
125
Denis Vlasenko079f8af2006-11-27 16:49:31 +0000126 return control_stream;
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000127}
128
Rob Landleyb1c3fbc2006-05-04 19:52:28 +0000129#if !ENABLE_FTPGET
Denis Vlasenko7039a662006-10-08 17:54:47 +0000130int ftp_receive(ftp_host_info_t *server, FILE *control_stream,
131 const char *local_path, char *server_path);
Rob Landleyb1c3fbc2006-05-04 19:52:28 +0000132#else
Denis Vlasenko7039a662006-10-08 17:54:47 +0000133static
134int ftp_receive(ftp_host_info_t *server, FILE *control_stream,
Eric Andersen04d055f2003-11-03 21:20:18 +0000135 const char *local_path, char *server_path)
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000136{
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000137 char buf[512];
Denis Vlasenko714701c2006-12-22 00:21:07 +0000138/* I think 'filesize' usage here is bogus. Let's see... */
139 //off_t filesize = -1;
140#define filesize ((off_t)-1)
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000141 int fd_data;
Glenn L McGrath236e93d2003-12-20 05:43:34 +0000142 int fd_local = -1;
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000143 off_t beg_range = 0;
144
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000145 /* Connect to the data socket */
146 if (ftpcmd("PASV", NULL, control_stream, buf) != 227) {
Denis Vlasenko562dc242007-01-03 21:55:50 +0000147 ftp_die("PASV", buf);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000148 }
Eric Andersen04d055f2003-11-03 21:20:18 +0000149 fd_data = xconnect_ftpdata(server, buf);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000150
Denis Vlasenko562dc242007-01-03 21:55:50 +0000151 if (ftpcmd("SIZE", server_path, control_stream, buf) == 213) {
Denis Vlasenko714701c2006-12-22 00:21:07 +0000152 //filesize = BB_STRTOOFF(buf + 4, NULL, 10);
153 //if (errno || filesize < 0)
Denis Vlasenko562dc242007-01-03 21:55:50 +0000154 // ftp_die("SIZE", buf);
Rob Landleybc059bc2006-01-10 06:36:00 +0000155 } else {
Rob Landleybc059bc2006-01-10 06:36:00 +0000156 do_continue = 0;
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000157 }
158
Denis Vlasenko9f739442006-12-16 23:49:13 +0000159 if (LONE_DASH(local_path)) {
Eric Andersen70060d22004-03-27 10:02:48 +0000160 fd_local = STDOUT_FILENO;
Glenn L McGrath236e93d2003-12-20 05:43:34 +0000161 do_continue = 0;
162 }
163
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000164 if (do_continue) {
165 struct stat sbuf;
Glenn L McGrath236e93d2003-12-20 05:43:34 +0000166 if (lstat(local_path, &sbuf) < 0) {
Denis Vlasenko7039a662006-10-08 17:54:47 +0000167 bb_perror_msg_and_die("lstat");
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000168 }
169 if (sbuf.st_size > 0) {
170 beg_range = sbuf.st_size;
171 } else {
172 do_continue = 0;
173 }
174 }
175
176 if (do_continue) {
Denis Vlasenkocf30cc82006-11-24 14:53:18 +0000177 sprintf(buf, "REST %"OFF_FMT"d", beg_range);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000178 if (ftpcmd(buf, NULL, control_stream, buf) != 350) {
179 do_continue = 0;
180 } else {
Denis Vlasenko714701c2006-12-22 00:21:07 +0000181 //if (filesize != -1)
182 // filesize -= beg_range;
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000183 }
184 }
185
Denis Vlasenko562dc242007-01-03 21:55:50 +0000186 if (ftpcmd("RETR", server_path, control_stream, buf) > 150) {
187 ftp_die("RETR", buf);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000188 }
189
Glenn L McGrath1643f412002-12-18 02:47:40 +0000190 /* only make a local file if we know that one exists on the remote server */
Glenn L McGrath236e93d2003-12-20 05:43:34 +0000191 if (fd_local == -1) {
192 if (do_continue) {
Rob Landleyd921b2e2006-08-03 15:41:12 +0000193 fd_local = xopen(local_path, O_APPEND | O_WRONLY);
Glenn L McGrath236e93d2003-12-20 05:43:34 +0000194 } else {
Denis Vlasenkocf749bc2006-11-26 15:45:17 +0000195 fd_local = xopen(local_path, O_CREAT | O_TRUNC | O_WRONLY);
Glenn L McGrath236e93d2003-12-20 05:43:34 +0000196 }
Glenn L McGrath1643f412002-12-18 02:47:40 +0000197 }
198
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000199 /* Copy the file */
Rob Landleybc059bc2006-01-10 06:36:00 +0000200 if (filesize != -1) {
Denis Vlasenko714701c2006-12-22 00:21:07 +0000201 if (bb_copyfd_size(fd_data, fd_local, filesize) == -1)
202 return EXIT_FAILURE;
Rob Landleybc059bc2006-01-10 06:36:00 +0000203 } else {
Denis Vlasenko714701c2006-12-22 00:21:07 +0000204 if (bb_copyfd_eof(fd_data, fd_local) == -1)
205 return EXIT_FAILURE;
Glenn L McGrath25fe94f2002-12-13 08:20:44 +0000206 }
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000207
208 /* close it all down */
209 close(fd_data);
210 if (ftpcmd(NULL, NULL, control_stream, buf) != 226) {
Denis Vlasenko562dc242007-01-03 21:55:50 +0000211 ftp_die(NULL, buf);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000212 }
213 ftpcmd("QUIT", NULL, control_stream, buf);
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000214
Denis Vlasenko079f8af2006-11-27 16:49:31 +0000215 return EXIT_SUCCESS;
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000216}
217#endif
218
Rob Landleyb1c3fbc2006-05-04 19:52:28 +0000219#if !ENABLE_FTPPUT
Denis Vlasenko7039a662006-10-08 17:54:47 +0000220int ftp_send(ftp_host_info_t *server, FILE *control_stream,
221 const char *server_path, char *local_path);
Rob Landleyb1c3fbc2006-05-04 19:52:28 +0000222#else
Denis Vlasenko7039a662006-10-08 17:54:47 +0000223static
224int ftp_send(ftp_host_info_t *server, FILE *control_stream,
Eric Andersen04d055f2003-11-03 21:20:18 +0000225 const char *server_path, char *local_path)
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000226{
227 struct stat sbuf;
228 char buf[512];
229 int fd_data;
230 int fd_local;
231 int response;
232
233 /* Connect to the data socket */
234 if (ftpcmd("PASV", NULL, control_stream, buf) != 227) {
Denis Vlasenko562dc242007-01-03 21:55:50 +0000235 ftp_die("PASV", buf);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000236 }
Eric Andersen04d055f2003-11-03 21:20:18 +0000237 fd_data = xconnect_ftpdata(server, buf);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000238
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000239 /* get the local file */
Denis Vlasenko9f739442006-12-16 23:49:13 +0000240 fd_local = STDIN_FILENO;
241 if (NOT_LONE_DASH(local_path)) {
Rob Landleyd921b2e2006-08-03 15:41:12 +0000242 fd_local = xopen(local_path, O_RDONLY);
Glenn L McGrath236e93d2003-12-20 05:43:34 +0000243 fstat(fd_local, &sbuf);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000244
Denis Vlasenko562dc242007-01-03 21:55:50 +0000245 sprintf(buf, "ALLO %"OFF_FMT"u", sbuf.st_size);
Glenn L McGrath236e93d2003-12-20 05:43:34 +0000246 response = ftpcmd(buf, NULL, control_stream, buf);
247 switch (response) {
248 case 200:
249 case 202:
250 break;
251 default:
252 close(fd_local);
Denis Vlasenko562dc242007-01-03 21:55:50 +0000253 ftp_die("ALLO", buf);
Glenn L McGrath236e93d2003-12-20 05:43:34 +0000254 break;
255 }
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000256 }
Denis Vlasenko562dc242007-01-03 21:55:50 +0000257 response = ftpcmd("STOR", server_path, control_stream, buf);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000258 switch (response) {
259 case 125:
260 case 150:
261 break;
262 default:
263 close(fd_local);
Denis Vlasenko562dc242007-01-03 21:55:50 +0000264 ftp_die("STOR", buf);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000265 }
266
267 /* transfer the file */
Glenn L McGrath7ffe1332003-11-21 22:24:57 +0000268 if (bb_copyfd_eof(fd_local, fd_data) == -1) {
Glenn L McGrath25fe94f2002-12-13 08:20:44 +0000269 exit(EXIT_FAILURE);
270 }
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000271
272 /* close it all down */
273 close(fd_data);
274 if (ftpcmd(NULL, NULL, control_stream, buf) != 226) {
Denis Vlasenko562dc242007-01-03 21:55:50 +0000275 ftp_die("close", buf);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000276 }
277 ftpcmd("QUIT", NULL, control_stream, buf);
278
Denis Vlasenko079f8af2006-11-27 16:49:31 +0000279 return EXIT_SUCCESS;
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000280}
281#endif
282
Glenn L McGrathb51eb262003-12-19 10:37:52 +0000283#define FTPGETPUT_OPT_CONTINUE 1
284#define FTPGETPUT_OPT_VERBOSE 2
285#define FTPGETPUT_OPT_USER 4
286#define FTPGETPUT_OPT_PASSWORD 8
287#define FTPGETPUT_OPT_PORT 16
288
Bernhard Reutner-Fischer01d23ad2006-05-26 20:19:22 +0000289#if ENABLE_FEATURE_FTPGETPUT_LONG_OPTIONS
Glenn L McGrathb51eb262003-12-19 10:37:52 +0000290static const struct option ftpgetput_long_options[] = {
Denis Vlasenkoc61852a2006-11-29 11:09:43 +0000291 { "continue", 1, NULL, 'c' },
292 { "verbose", 0, NULL, 'v' },
293 { "username", 1, NULL, 'u' },
294 { "password", 1, NULL, 'p' },
295 { "port", 1, NULL, 'P' },
296 { 0, 0, 0, 0 }
Glenn L McGrathb51eb262003-12-19 10:37:52 +0000297};
Bernhard Reutner-Fischer01d23ad2006-05-26 20:19:22 +0000298#endif
Glenn L McGrathb51eb262003-12-19 10:37:52 +0000299
Denis Vlasenko06af2162007-02-03 17:28:39 +0000300int ftpgetput_main(int argc, char **argv);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000301int ftpgetput_main(int argc, char **argv)
302{
303 /* content-length of the file */
Denis Vlasenko67b23e62006-10-03 21:00:06 +0000304 unsigned opt;
Denis Vlasenko562dc242007-01-03 21:55:50 +0000305 const char *port = "ftp";
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000306 /* socket to ftp server */
307 FILE *control_stream;
Denis Vlasenko562dc242007-01-03 21:55:50 +0000308 /* continue previous transfer (-c) */
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000309 ftp_host_info_t *server;
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000310
Denis Vlasenko562dc242007-01-03 21:55:50 +0000311#if ENABLE_FTPPUT && !ENABLE_FTPGET
312# define ftp_action ftp_send
313#elif ENABLE_FTPGET && !ENABLE_FTPPUT
314# define ftp_action ftp_receive
315#else
316 int (*ftp_action)(ftp_host_info_t *, FILE *, const char *, char *) = ftp_send;
Glenn L McGrath266c1f52003-12-20 03:19:27 +0000317 /* Check to see if the command is ftpget or ftput */
Denis Vlasenko562dc242007-01-03 21:55:50 +0000318 if (applet_name[3] == 'g') {
Bernhard Reutner-Fischere0387a62006-06-07 13:31:59 +0000319 ftp_action = ftp_receive;
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000320 }
Denis Vlasenko562dc242007-01-03 21:55:50 +0000321#endif
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000322
323 /* Set default values */
Denis Vlasenko4fa5e8b2007-01-11 22:39:25 +0000324 server = xmalloc(sizeof(*server));
Glenn L McGrath266c1f52003-12-20 03:19:27 +0000325 server->user = "anonymous";
326 server->password = "busybox@";
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000327
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000328 /*
329 * Decipher the command line
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000330 */
Denis Vlasenkoc61852a2006-11-29 11:09:43 +0000331#if ENABLE_FEATURE_FTPGETPUT_LONG_OPTIONS
332 applet_long_options = ftpgetput_long_options;
333#endif
Denis Vlasenko562dc242007-01-03 21:55:50 +0000334 opt_complementary = "=3"; /* must have 3 params */
Denis Vlasenko67b23e62006-10-03 21:00:06 +0000335 opt = getopt32(argc, argv, "cvu:p:P:", &server->user, &server->password, &port);
Denis Vlasenko562dc242007-01-03 21:55:50 +0000336 argv += optind;
Glenn L McGrath236e93d2003-12-20 05:43:34 +0000337
338 /* Process the non-option command line arguments */
Glenn L McGrathb51eb262003-12-19 10:37:52 +0000339 if (opt & FTPGETPUT_OPT_CONTINUE) {
340 do_continue = 1;
341 }
342 if (opt & FTPGETPUT_OPT_VERBOSE) {
343 verbose_flag = 1;
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000344 }
345
Eric Andersen04d055f2003-11-03 21:20:18 +0000346 /* We want to do exactly _one_ DNS lookup, since some
347 * sites (i.e. ftp.us.debian.org) use round-robin DNS
348 * and we want to connect to only one IP... */
Denis Vlasenko8e9ccba2007-01-11 16:50:23 +0000349 server->lsa = host2sockaddr(argv[0], bb_lookup_port(port, "tcp", 21));
Eric Andersen04d055f2003-11-03 21:20:18 +0000350 if (verbose_flag) {
Denis Vlasenko85629f02007-01-22 09:36:41 +0000351 printf("Connecting to %s (%s)\n", argv[0],
Denis Vlasenko8e9ccba2007-01-11 16:50:23 +0000352 xmalloc_sockaddr2dotted(&server->lsa->sa, server->lsa->len));
Eric Andersen04d055f2003-11-03 21:20:18 +0000353 }
354
355 /* Connect/Setup/Configure the FTP session */
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000356 control_stream = ftp_login(server);
357
Denis Vlasenko562dc242007-01-03 21:55:50 +0000358 return ftp_action(server, control_stream, argv[1], argv[2]);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000359}