18471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma/* ftpget.c - Get a remote file from FTP.
28471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma *
38471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma * Copyright 2013 Ranjan Kumar <ranjankumar.bth@gmail.com>
48471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma * Copyright 2013 Kyungwan Han <asura321@gmail.com>
58471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma *
68471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma * No Standard.
78471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma *
8fc33eb78115adf8a90875f822706bdf3d462524cIsaac DunhamUSE_FTPGET(NEWTOY(ftpget, "<2cvu:p:P#<0=21>65535", TOYFLAG_BIN))
9f3e56f4e4ff773de95fa2c9daf979734d826fc33Rob LandleyUSE_FTPGET(OLDTOY(ftpput, ftpget, TOYFLAG_BIN))
108471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
118471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharmaconfig FTPGET
128471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  bool "ftpget/ftpput"
138471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  default n
148471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  help
15fc33eb78115adf8a90875f822706bdf3d462524cIsaac Dunham    usage: ftpget [-cv] [-u USER -p PASSWORD -P PORT] HOST_NAME [LOCAL_FILENAME] REMOTE_FILENAME
16fc33eb78115adf8a90875f822706bdf3d462524cIsaac Dunham    usage: ftpput [-v] [-u USER -p PASSWORD -P PORT] HOST_NAME [REMOTE_FILENAME] LOCAL_FILENAME
178471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
188471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma    ftpget - Get a remote file from FTP.
198471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma    ftpput - Upload a local file on remote machine through FTP.
208471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
218471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma    -c Continue previous transfer.
228471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma    -v Verbose.
238471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma    -u User name.
248471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma    -p Password.
25fc33eb78115adf8a90875f822706bdf3d462524cIsaac Dunham    -P Port Number (default 21).
268471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma*/
278471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma#define FOR_ftpget
288471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma#include "toys.h"
298471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
308471dc08c411822480b2bf622a5ea7fce1cef33dAshwini SharmaGLOBALS(
31fc33eb78115adf8a90875f822706bdf3d462524cIsaac Dunham  long port; //  char *port;
328471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  char *password;
338471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  char *username;
348471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
358471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  FILE *sockfp;
368471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  int c;
378471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  int isget;
388471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  char buf[sizeof(struct sockaddr_storage)];
398471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma)
408471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
418471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma#define DATACONNECTION_OPENED   125
428471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma#define FTPFILE_STATUSOKAY      150
438471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma#define FTP_COMMAND_OKAY        200
448471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma#define FTPFILE_STATUS          213
458471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma#define FTPSERVER_READY         220
468471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma#define CLOSE_DATACONECTION     226
478471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma#define PASSIVE_MODE            227
488471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma#define USERLOGGED_SUCCESS      230
498471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma#define PASSWORD_REQUEST        331
508471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma#define REQUESTED_PENDINGACTION 350
518471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
528471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
538471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharmastatic void setport(unsigned port_num)
548471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma{
558471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  int af = ((struct sockaddr *)TT.buf)->sa_family;
568471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
578471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  if (af == AF_INET) ((struct sockaddr_in*)TT.buf)->sin_port = port_num;
588471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  else if (af == AF_INET6) ((struct sockaddr_in6*)TT.buf)->sin6_port = port_num;
598471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma}
608471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
618471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharmastatic int connect_to_stream()
628471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma{
638471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  int sockfd, af = ((struct sockaddr *)TT.buf)->sa_family;
648471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
658471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  sockfd = xsocket(af, SOCK_STREAM, 0);
668471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  if (connect(sockfd, (struct sockaddr*)TT.buf,((af == AF_INET)?
678471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma          sizeof(struct sockaddr_in):sizeof(struct sockaddr_in6))) < 0) {
688471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma    close(sockfd);
698471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma    perror_exit("can't connect to remote host");
708471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  }
718471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  return sockfd;
728471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma}
738471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
748471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma//close ftp connection and print the message.
758471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharmastatic void close_stream(char *msg_str)
768471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma{
778471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  char *str = toybuf; //toybuf holds response data.
788471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
798471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  //Remove garbage chars (from ' ' space to '\x7f') DEL remote server response.
808471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  while ((*str >= 0x20) && (*str < 0x7f)) str++;
818471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  *str = '\0';
828471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  if (TT.sockfp) fclose(TT.sockfp);
838471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  error_exit("%s server response: %s", (msg_str) ? msg_str:"", toybuf);
848471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma}
858471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
868471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma//send command to ftp and get return status.
878471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharmastatic int get_ftp_response(char *command, char *param)
888471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma{
898471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  unsigned cmd_status = 0;
908471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  char *fmt = "%s %s\r\n";
918471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
928471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  if (command) {
938471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma    if (!param) fmt += 3;
948471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma    fprintf(TT.sockfp, fmt, command, param);
958471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma    fflush(TT.sockfp);
968471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma    if (toys.optflags & FLAG_v)
978471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma      fprintf(stderr, "FTP Request: %s %s\r\n", command, param);
988471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  }
998471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
1008471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  do {
1018471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma    if (!fgets(toybuf, sizeof(toybuf)-1, TT.sockfp)) close_stream(NULL);
1028471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  } while (!isdigit(toybuf[0]) || toybuf[3] != ' ');
1038471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
1048471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  toybuf[3] = '\0';
1058471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  cmd_status = atolx_range(toybuf, 0, INT_MAX);
1068471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  toybuf[3] = ' ';
1078471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  return cmd_status;
1088471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma}
1098471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
1108471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharmastatic void send_requests(void)
1118471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma{
1128471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  int cmd_status = 0;
1138471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
1148471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  //FTP connection request.
1158471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  if (get_ftp_response(NULL, NULL) != FTPSERVER_READY) close_stream(NULL);
1168471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
1178471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  //230 User authenticated, password please; 331 Password request.
1188471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  cmd_status = get_ftp_response("USER", TT.username);
1198471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  if (cmd_status == PASSWORD_REQUEST) { //user logged in. Need Password.
1208471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma    if (get_ftp_response("PASS", TT.password) != USERLOGGED_SUCCESS)
1218471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma      close_stream("PASS");
1228471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  } else if (cmd_status == USERLOGGED_SUCCESS); //do nothing
1238471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  else close_stream("USER");
1248471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  //200 Type Binary. Command okay.
1258471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  if (get_ftp_response("TYPE I", NULL) != FTP_COMMAND_OKAY)
1268471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma    close_stream("TYPE I");
1278471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma}
1288471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
1298471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharmastatic void get_sockaddr(char *host)
1308471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma{
1318471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  struct addrinfo hints, *result;
13230f6ef5fcd571c554c2c59585d126b92793379d0Ashwini Sharma  char port[6];
133fc33eb78115adf8a90875f822706bdf3d462524cIsaac Dunham  int status;
1348471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
1358471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  errno = 0;
136fc33eb78115adf8a90875f822706bdf3d462524cIsaac Dunham  snprintf(port, 6, "%ld", TT.port);
1378471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
1388471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  memset(&hints, 0 , sizeof(struct addrinfo));
1398471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  hints.ai_family = AF_UNSPEC;
1408471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  hints.ai_socktype = SOCK_STREAM;
1418471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
142fc33eb78115adf8a90875f822706bdf3d462524cIsaac Dunham  status = getaddrinfo(host, port, &hints, &result);
1438471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  if (status) error_exit("bad address '%s' : %s", host, gai_strerror(status));
1448471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
1458471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  memcpy(TT.buf, result->ai_addr, result->ai_addrlen);
1468471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  freeaddrinfo(result);
1478471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma}
1488471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
1498471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma// send commands to ftp fo PASV mode.
1508471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharmastatic void verify_pasv_mode(char *r_filename)
1518471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma{
1528471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  char *pch;
1538471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  unsigned portnum;
1548471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
1558471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  //vsftpd reply like:- "227 Entering Passive Mode (125,19,39,117,43,39)".
1567eb3e4364c2bcebd2fdfef52c07f5101aa03e5bbAshwini Sharma  if (get_ftp_response("PASV", NULL) != PASSIVE_MODE) goto close_stream;
1578471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
1588471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  //Response is "NNN <some text> (N1,N2,N3,N4,P1,P2) garbage.
1598471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  //Server's IP is N1.N2.N3.N4
1608471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  //Server's port for data connection is P1*256+P2.
1617eb3e4364c2bcebd2fdfef52c07f5101aa03e5bbAshwini Sharma  if (!(pch = strrchr(toybuf, ')'))) goto close_stream;
1627eb3e4364c2bcebd2fdfef52c07f5101aa03e5bbAshwini Sharma  *pch = '\0';
1637eb3e4364c2bcebd2fdfef52c07f5101aa03e5bbAshwini Sharma  if (!(pch = strrchr(toybuf, ','))) goto close_stream;
1647eb3e4364c2bcebd2fdfef52c07f5101aa03e5bbAshwini Sharma  *pch = '\0';
1657eb3e4364c2bcebd2fdfef52c07f5101aa03e5bbAshwini Sharma
1668471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  portnum = atolx_range(pch + 1, 0, 255);
1678471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
1687eb3e4364c2bcebd2fdfef52c07f5101aa03e5bbAshwini Sharma  if (!(pch = strrchr(toybuf, ','))) goto close_stream;
1697eb3e4364c2bcebd2fdfef52c07f5101aa03e5bbAshwini Sharma  *pch = '\0';
1708471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  portnum = portnum + (atolx_range(pch + 1, 0, 255) * 256);
1718471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  setport(htons(portnum));
1728471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
1738471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  if (TT.isget && get_ftp_response("SIZE", r_filename) != FTPFILE_STATUS)
1748471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma    TT.c = 0;
1757eb3e4364c2bcebd2fdfef52c07f5101aa03e5bbAshwini Sharma  return;
1767eb3e4364c2bcebd2fdfef52c07f5101aa03e5bbAshwini Sharma
1777eb3e4364c2bcebd2fdfef52c07f5101aa03e5bbAshwini Sharmaclose_stream:
1787eb3e4364c2bcebd2fdfef52c07f5101aa03e5bbAshwini Sharma  close_stream("PASV");
1798471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma}
1808471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
1818471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma/*
1828471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma * verify the local file presence.
1838471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma * if present, get the size of the file.
1848471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma */
1858471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharmastatic void is_localfile_present(char *l_filename)
1868471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma{
1878471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  struct stat sb;
1888471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
1898471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  if (stat(l_filename, &sb) < 0) perror_exit("stat");
1908471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  //if local file present, then request for pending file action.
1918471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  if (sb.st_size > 0) {
1928471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma    sprintf(toybuf, "REST %lu", (unsigned long) sb.st_size);
1938471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma    if (get_ftp_response(toybuf, NULL) != REQUESTED_PENDINGACTION) TT.c = 0;
1948471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  } else TT.c = 0;
1958471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma}
1968471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
1978471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharmastatic void transfer_file(int local_fd, int remote_fd)
1988471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma{
1998471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  int len, rfd = (TT.isget)?remote_fd:local_fd,
2008471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma      wfd = (TT.isget)?local_fd:remote_fd;
2018471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
2028471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  if (rfd < 0 || wfd < 0) error_exit("Error in file creation:");
2038471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  while ((len = xread(rfd, toybuf, sizeof(toybuf)))) xwrite(wfd, toybuf, len);
2048471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma}
2058471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
2068471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharmastatic void get_file(char *l_filename, char *r_filename)
2078471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma{
2088471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  int local_fd = -1, remote_fd;
2098471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
2108471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  verify_pasv_mode(r_filename);
2118471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  remote_fd = connect_to_stream(); //Connect to data socket.
2128471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
2138471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  //if local file name will be '-' then local fd will be stdout.
2148471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  if ((l_filename[0] == '-') && !l_filename[1]) {
2158471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma    local_fd = 1; //file descriptor will become stdout.
2168471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma    TT.c = 0;
2178471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  }
2188471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
2198471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  //if continue, check for local file existance.
2208471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  if (TT.c) is_localfile_present(l_filename);
2218471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
2228471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  //verify the remote file presence.
2238471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  if (get_ftp_response("RETR", r_filename) > FTPFILE_STATUSOKAY)
2248471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma    close_stream("RETR");
2258471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
2268471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  //if local fd is not stdout, create a file descriptor.
2278471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  if (local_fd == -1) {
2288471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma    int flags = O_WRONLY;
2298471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
2308471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma    flags |= (TT.c)? O_APPEND : (O_CREAT | O_TRUNC);
2318471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma    local_fd = xcreate((char *)l_filename, flags, 0666);
2328471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  }
2338471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  transfer_file(local_fd, remote_fd);
2348471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  xclose(remote_fd);
2358471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  xclose(local_fd);
2368471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  if (get_ftp_response(NULL, NULL) != CLOSE_DATACONECTION) close_stream(NULL);
2378471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  get_ftp_response("QUIT", NULL);
2388471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  toys.exitval = EXIT_SUCCESS;
2398471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma}
2408471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
2418471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharmastatic void put_file(char *r_filename, char *l_filename)
2428471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma{
2438471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  int local_fd = 0, remote_fd;
2448471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  unsigned cmd_status = 0;
2458471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
2468471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  verify_pasv_mode(r_filename);
2478471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  remote_fd = connect_to_stream(); //Connect to data socket.
2488471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
2498471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  //open the local file for transfer.
2508471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  if ((l_filename[0] != '-') || l_filename[1])
2518471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma    local_fd = xcreate((char *)l_filename, O_RDONLY, 0666);
2528471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
2538471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  //verify for the remote file status, Ok or Open: transfer File.
2548471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  cmd_status = get_ftp_response("STOR", r_filename);
2558471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  if ( (cmd_status == DATACONNECTION_OPENED) ||
2568471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma      (cmd_status == FTPFILE_STATUSOKAY)) {
2578471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma    transfer_file(local_fd, remote_fd);
2588471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma    if (get_ftp_response(NULL, NULL) != CLOSE_DATACONECTION) close_stream(NULL);
2598471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma    get_ftp_response("QUIT", NULL);
2608471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma    toys.exitval = EXIT_SUCCESS;
2618471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  } else {
2628471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma    toys.exitval = EXIT_FAILURE;
2638471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma    close_stream("STOR");
2648471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  }
2658471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  xclose(remote_fd);
2668471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  xclose(local_fd);
2678471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma}
2688471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
2698471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharmavoid ftpget_main(void)
2708471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma{
2718471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  char **argv = toys.optargs; //host name + file name.
2728471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
2738471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  TT.isget = toys.which->name[3] == 'g';
2748471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  TT.c = 1;
2758471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  //if user name is not specified.
2768471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  if (!(toys.optflags & FLAG_u) && (toys.optflags & FLAG_p))
2778471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma    error_exit("Missing username:");
2788471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  //if user name and password is not specified in command line.
2798471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  if (!(toys.optflags & FLAG_u) && !(toys.optflags & FLAG_p))
2808471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma    TT.username = TT.password ="anonymous";
2818471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
2828471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  //if continue is not in the command line argument.
2838471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  if (TT.isget && !(toys.optflags & FLAG_c)) TT.c = 0;
2848471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
2858471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  if (toys.optflags & FLAG_v) fprintf(stderr, "Connecting to %s\n", argv[0]);
2868471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  get_sockaddr(argv[0]);
2878471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
2888471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  TT.sockfp = xfdopen(connect_to_stream(), "r+");
2898471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  send_requests();
2908471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma
2918471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  if (TT.isget) get_file(argv[1], argv[2] ? argv[2] : argv[1]);
2928471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma  else put_file(argv[1], argv[2] ? argv[2] : argv[1]);
2938471dc08c411822480b2bf622a5ea7fce1cef33dAshwini Sharma}
294