blob: a1ee054263cc79d6e89480cf56291d18392213a9 [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
Denis Vlasenko562dc242007-01-03 21:55:50 +000071static int xconnect_ftpdata(ftp_host_info_t *server, char *buf)
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000072{
73 char *buf_ptr;
Denis Vlasenko284d0fa2008-02-16 13:18:17 +000074 unsigned port_num;
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000075
Denis Vlasenko562dc242007-01-03 21:55:50 +000076 /* Response is "NNN garbageN1,N2,N3,N4,P1,P2[)garbage]
77 * Server's IP is N1.N2.N3.N4 (we ignore it)
78 * Server's port for data connection is P1*256+P2 */
79 buf_ptr = strrchr(buf, ')');
80 if (buf_ptr) *buf_ptr = '\0';
81
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000082 buf_ptr = strrchr(buf, ',');
83 *buf_ptr = '\0';
Denis Vlasenko13858992006-10-08 12:49:22 +000084 port_num = xatoul_range(buf_ptr + 1, 0, 255);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000085
86 buf_ptr = strrchr(buf, ',');
87 *buf_ptr = '\0';
Denis Vlasenko13858992006-10-08 12:49:22 +000088 port_num += xatoul_range(buf_ptr + 1, 0, 255) * 256;
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000089
Denis Vlasenko5d687242007-01-12 20:59:31 +000090 set_nport(server->lsa, htons(port_num));
Denis Vlasenko8e9ccba2007-01-11 16:50:23 +000091 return xconnect_stream(server->lsa);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000092}
93
94static FILE *ftp_login(ftp_host_info_t *server)
95{
96 FILE *control_stream;
97 char buf[512];
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +000098
99 /* Connect to the command socket */
Denis Vlasenko8e9ccba2007-01-11 16:50:23 +0000100 control_stream = fdopen(xconnect_stream(server->lsa), "r+");
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000101 if (control_stream == NULL) {
Denis Vlasenko8e9ccba2007-01-11 16:50:23 +0000102 /* fdopen failed - extremely unlikely */
Denis Vlasenko562dc242007-01-03 21:55:50 +0000103 bb_perror_nomsg_and_die();
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000104 }
105
106 if (ftpcmd(NULL, NULL, control_stream, buf) != 220) {
Denis Vlasenko562dc242007-01-03 21:55:50 +0000107 ftp_die(NULL, buf);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000108 }
109
110 /* Login to the server */
Denis Vlasenko562dc242007-01-03 21:55:50 +0000111 switch (ftpcmd("USER", server->user, control_stream, buf)) {
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000112 case 230:
113 break;
114 case 331:
Denis Vlasenko562dc242007-01-03 21:55:50 +0000115 if (ftpcmd("PASS", server->password, control_stream, buf) != 230) {
116 ftp_die("PASS", buf);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000117 }
118 break;
119 default:
Denis Vlasenko562dc242007-01-03 21:55:50 +0000120 ftp_die("USER", buf);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000121 }
122
123 ftpcmd("TYPE I", NULL, control_stream, buf);
124
Denis Vlasenko079f8af2006-11-27 16:49:31 +0000125 return control_stream;
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000126}
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
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000144 /* Connect to the data socket */
145 if (ftpcmd("PASV", NULL, control_stream, buf) != 227) {
Denis Vlasenko562dc242007-01-03 21:55:50 +0000146 ftp_die("PASV", buf);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000147 }
Eric Andersen04d055f2003-11-03 21:20:18 +0000148 fd_data = xconnect_ftpdata(server, buf);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000149
Denis Vlasenko562dc242007-01-03 21:55:50 +0000150 if (ftpcmd("SIZE", server_path, control_stream, buf) == 213) {
Denis Vlasenko714701c2006-12-22 00:21:07 +0000151 //filesize = BB_STRTOOFF(buf + 4, NULL, 10);
152 //if (errno || filesize < 0)
Denis Vlasenko562dc242007-01-03 21:55:50 +0000153 // ftp_die("SIZE", buf);
Rob Landleybc059bc2006-01-10 06:36:00 +0000154 } else {
Rob Landleybc059bc2006-01-10 06:36:00 +0000155 do_continue = 0;
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000156 }
157
Denis Vlasenko9f739442006-12-16 23:49:13 +0000158 if (LONE_DASH(local_path)) {
Eric Andersen70060d22004-03-27 10:02:48 +0000159 fd_local = STDOUT_FILENO;
Glenn L McGrath236e93d2003-12-20 05:43:34 +0000160 do_continue = 0;
161 }
162
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000163 if (do_continue) {
164 struct stat sbuf;
Glenn L McGrath236e93d2003-12-20 05:43:34 +0000165 if (lstat(local_path, &sbuf) < 0) {
Denis Vlasenko7039a662006-10-08 17:54:47 +0000166 bb_perror_msg_and_die("lstat");
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000167 }
168 if (sbuf.st_size > 0) {
169 beg_range = sbuf.st_size;
170 } else {
171 do_continue = 0;
172 }
173 }
174
175 if (do_continue) {
Denis Vlasenkocf30cc82006-11-24 14:53:18 +0000176 sprintf(buf, "REST %"OFF_FMT"d", beg_range);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000177 if (ftpcmd(buf, NULL, control_stream, buf) != 350) {
178 do_continue = 0;
179 } else {
Denis Vlasenko714701c2006-12-22 00:21:07 +0000180 //if (filesize != -1)
181 // filesize -= beg_range;
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000182 }
183 }
184
Denis Vlasenko562dc242007-01-03 21:55:50 +0000185 if (ftpcmd("RETR", server_path, control_stream, buf) > 150) {
186 ftp_die("RETR", buf);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000187 }
188
Glenn L McGrath1643f412002-12-18 02:47:40 +0000189 /* only make a local file if we know that one exists on the remote server */
Glenn L McGrath236e93d2003-12-20 05:43:34 +0000190 if (fd_local == -1) {
191 if (do_continue) {
Rob Landleyd921b2e2006-08-03 15:41:12 +0000192 fd_local = xopen(local_path, O_APPEND | O_WRONLY);
Glenn L McGrath236e93d2003-12-20 05:43:34 +0000193 } else {
Denis Vlasenkocf749bc2006-11-26 15:45:17 +0000194 fd_local = xopen(local_path, O_CREAT | O_TRUNC | O_WRONLY);
Glenn L McGrath236e93d2003-12-20 05:43:34 +0000195 }
Glenn L McGrath1643f412002-12-18 02:47:40 +0000196 }
197
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000198 /* Copy the file */
Rob Landleybc059bc2006-01-10 06:36:00 +0000199 if (filesize != -1) {
Denis Vlasenko714701c2006-12-22 00:21:07 +0000200 if (bb_copyfd_size(fd_data, fd_local, filesize) == -1)
201 return EXIT_FAILURE;
Rob Landleybc059bc2006-01-10 06:36:00 +0000202 } else {
Denis Vlasenko714701c2006-12-22 00:21:07 +0000203 if (bb_copyfd_eof(fd_data, fd_local) == -1)
204 return EXIT_FAILURE;
Glenn L McGrath25fe94f2002-12-13 08:20:44 +0000205 }
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000206
207 /* close it all down */
208 close(fd_data);
209 if (ftpcmd(NULL, NULL, control_stream, buf) != 226) {
Denis Vlasenko562dc242007-01-03 21:55:50 +0000210 ftp_die(NULL, buf);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000211 }
212 ftpcmd("QUIT", NULL, control_stream, buf);
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000213
Denis Vlasenko079f8af2006-11-27 16:49:31 +0000214 return EXIT_SUCCESS;
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000215}
216#endif
217
Rob Landleyb1c3fbc2006-05-04 19:52:28 +0000218#if !ENABLE_FTPPUT
Denis Vlasenko7039a662006-10-08 17:54:47 +0000219int ftp_send(ftp_host_info_t *server, FILE *control_stream,
220 const char *server_path, char *local_path);
Rob Landleyb1c3fbc2006-05-04 19:52:28 +0000221#else
Denis Vlasenko7039a662006-10-08 17:54:47 +0000222static
223int ftp_send(ftp_host_info_t *server, FILE *control_stream,
Eric Andersen04d055f2003-11-03 21:20:18 +0000224 const char *server_path, char *local_path)
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000225{
226 struct stat sbuf;
227 char buf[512];
228 int fd_data;
229 int fd_local;
230 int response;
231
232 /* Connect to the data socket */
233 if (ftpcmd("PASV", NULL, control_stream, buf) != 227) {
Denis Vlasenko562dc242007-01-03 21:55:50 +0000234 ftp_die("PASV", buf);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000235 }
Eric Andersen04d055f2003-11-03 21:20:18 +0000236 fd_data = xconnect_ftpdata(server, buf);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000237
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000238 /* get the local file */
Denis Vlasenko9f739442006-12-16 23:49:13 +0000239 fd_local = STDIN_FILENO;
240 if (NOT_LONE_DASH(local_path)) {
Rob Landleyd921b2e2006-08-03 15:41:12 +0000241 fd_local = xopen(local_path, O_RDONLY);
Glenn L McGrath236e93d2003-12-20 05:43:34 +0000242 fstat(fd_local, &sbuf);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000243
Denis Vlasenko562dc242007-01-03 21:55:50 +0000244 sprintf(buf, "ALLO %"OFF_FMT"u", sbuf.st_size);
Glenn L McGrath236e93d2003-12-20 05:43:34 +0000245 response = ftpcmd(buf, NULL, control_stream, buf);
246 switch (response) {
247 case 200:
248 case 202:
249 break;
250 default:
251 close(fd_local);
Denis Vlasenko562dc242007-01-03 21:55:50 +0000252 ftp_die("ALLO", buf);
Glenn L McGrath236e93d2003-12-20 05:43:34 +0000253 break;
254 }
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000255 }
Denis Vlasenko562dc242007-01-03 21:55:50 +0000256 response = ftpcmd("STOR", server_path, control_stream, buf);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000257 switch (response) {
258 case 125:
259 case 150:
260 break;
261 default:
262 close(fd_local);
Denis Vlasenko562dc242007-01-03 21:55:50 +0000263 ftp_die("STOR", buf);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000264 }
265
266 /* transfer the file */
Glenn L McGrath7ffe1332003-11-21 22:24:57 +0000267 if (bb_copyfd_eof(fd_local, fd_data) == -1) {
Glenn L McGrath25fe94f2002-12-13 08:20:44 +0000268 exit(EXIT_FAILURE);
269 }
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000270
271 /* close it all down */
272 close(fd_data);
273 if (ftpcmd(NULL, NULL, control_stream, buf) != 226) {
Denis Vlasenko562dc242007-01-03 21:55:50 +0000274 ftp_die("close", buf);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000275 }
276 ftpcmd("QUIT", NULL, control_stream, buf);
277
Denis Vlasenko079f8af2006-11-27 16:49:31 +0000278 return EXIT_SUCCESS;
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000279}
280#endif
281
Glenn L McGrathb51eb262003-12-19 10:37:52 +0000282#define FTPGETPUT_OPT_CONTINUE 1
283#define FTPGETPUT_OPT_VERBOSE 2
284#define FTPGETPUT_OPT_USER 4
285#define FTPGETPUT_OPT_PASSWORD 8
286#define FTPGETPUT_OPT_PORT 16
287
Bernhard Reutner-Fischer01d23ad2006-05-26 20:19:22 +0000288#if ENABLE_FEATURE_FTPGETPUT_LONG_OPTIONS
Denis Vlasenko6ca409e2007-08-12 20:58:27 +0000289static const char ftpgetput_longopts[] ALIGN1 =
Denis Vlasenkobdc88fd2007-07-23 17:14:14 +0000290 "continue\0" Required_argument "c"
291 "verbose\0" No_argument "v"
292 "username\0" Required_argument "u"
293 "password\0" Required_argument "p"
294 "port\0" Required_argument "P"
Denis Vlasenko990d0f62007-07-24 15:54:42 +0000295 ;
Bernhard Reutner-Fischer01d23ad2006-05-26 20:19:22 +0000296#endif
Glenn L McGrathb51eb262003-12-19 10:37:52 +0000297
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +0000298int ftpgetput_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
Denis Vlasenko68404f12008-03-17 09:00:54 +0000299int ftpgetput_main(int argc ATTRIBUTE_UNUSED, char **argv)
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000300{
301 /* content-length of the file */
Denis Vlasenko67b23e62006-10-03 21:00:06 +0000302 unsigned opt;
Denis Vlasenko562dc242007-01-03 21:55:50 +0000303 const char *port = "ftp";
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000304 /* socket to ftp server */
305 FILE *control_stream;
Denis Vlasenko562dc242007-01-03 21:55:50 +0000306 /* continue previous transfer (-c) */
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000307 ftp_host_info_t *server;
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000308
Denis Vlasenko562dc242007-01-03 21:55:50 +0000309#if ENABLE_FTPPUT && !ENABLE_FTPGET
310# define ftp_action ftp_send
311#elif ENABLE_FTPGET && !ENABLE_FTPPUT
312# define ftp_action ftp_receive
313#else
314 int (*ftp_action)(ftp_host_info_t *, FILE *, const char *, char *) = ftp_send;
Glenn L McGrath266c1f52003-12-20 03:19:27 +0000315 /* Check to see if the command is ftpget or ftput */
Denis Vlasenko562dc242007-01-03 21:55:50 +0000316 if (applet_name[3] == 'g') {
Bernhard Reutner-Fischere0387a62006-06-07 13:31:59 +0000317 ftp_action = ftp_receive;
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000318 }
Denis Vlasenko562dc242007-01-03 21:55:50 +0000319#endif
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000320
321 /* Set default values */
Denis Vlasenko4fa5e8b2007-01-11 22:39:25 +0000322 server = xmalloc(sizeof(*server));
Glenn L McGrath266c1f52003-12-20 03:19:27 +0000323 server->user = "anonymous";
324 server->password = "busybox@";
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000325
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000326 /*
327 * Decipher the command line
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000328 */
Denis Vlasenkoc61852a2006-11-29 11:09:43 +0000329#if ENABLE_FEATURE_FTPGETPUT_LONG_OPTIONS
Denis Vlasenkobdc88fd2007-07-23 17:14:14 +0000330 applet_long_options = ftpgetput_longopts;
Denis Vlasenkoc61852a2006-11-29 11:09:43 +0000331#endif
Denis Vlasenko562dc242007-01-03 21:55:50 +0000332 opt_complementary = "=3"; /* must have 3 params */
Denis Vlasenkofe7cd642007-08-18 15:32:12 +0000333 opt = getopt32(argv, "cvu:p:P:", &server->user, &server->password, &port);
Denis Vlasenko562dc242007-01-03 21:55:50 +0000334 argv += optind;
Glenn L McGrath236e93d2003-12-20 05:43:34 +0000335
336 /* Process the non-option command line arguments */
Glenn L McGrathb51eb262003-12-19 10:37:52 +0000337 if (opt & FTPGETPUT_OPT_CONTINUE) {
338 do_continue = 1;
339 }
340 if (opt & FTPGETPUT_OPT_VERBOSE) {
341 verbose_flag = 1;
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000342 }
343
Eric Andersen04d055f2003-11-03 21:20:18 +0000344 /* We want to do exactly _one_ DNS lookup, since some
345 * sites (i.e. ftp.us.debian.org) use round-robin DNS
346 * and we want to connect to only one IP... */
Denis Vlasenko42823d52007-02-04 02:39:08 +0000347 server->lsa = xhost2sockaddr(argv[0], bb_lookup_port(port, "tcp", 21));
Eric Andersen04d055f2003-11-03 21:20:18 +0000348 if (verbose_flag) {
Denis Vlasenko85629f02007-01-22 09:36:41 +0000349 printf("Connecting to %s (%s)\n", argv[0],
Bernhard Reutner-Fischer8c69afd2008-01-29 10:33:34 +0000350 xmalloc_sockaddr2dotted(&server->lsa->u.sa));
Eric Andersen04d055f2003-11-03 21:20:18 +0000351 }
352
353 /* Connect/Setup/Configure the FTP session */
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000354 control_stream = ftp_login(server);
355
Denis Vlasenko562dc242007-01-03 21:55:50 +0000356 return ftp_action(server, control_stream, argv[1], argv[2]);
Glenn L McGrath02d7cbf2002-12-13 02:43:50 +0000357}