Hi,
I am new to socket programming, I wrote an ftpclient which connects to an ftp server and downloads a file to the client computer.
Now in one client connection I want to download multiple files by forking the parent connection.
So far I have this, the code downloads only one file, and then gives the following error
"Transfer Completed425 Unable to build data connection: Invalid argument"
There is something basic that I am missing or taking an altogether wrong approach?
Appreciate if someone can help me here.
Code:
/*******************************************************************************
Object:		This is a ftp client which communicates with a ftp server
		on port 21 (ftp-data port 20 RFC 959)
Input:		IPAddress to connect to / username & password to connect to ftp server
		filename to be downloaded (with path if not in the ftp directory of the user)
Functioning:	Creates a ftp socket
		A connection is established with the ftp server at the ip addr. and port 21 
		After the connection is established user authentication is done with server 
		and response is received.
		Once the user is authenticated a request to download the specified file is sent to the ftp server
Output:		None (though specified file is downloaded to the client machine).

********************************************************************************/
#include <stdio.h>        /* for printf() and fprintf() */
#include <sys/socket.h>   /* for socket(), connect(), send(), and recv() */
#include <arpa/inet.h>    /* for sockaddr_in and inet_addr() */
#include <stdlib.h>       /* for atoi() */
#include <string.h>       /* for memset() */
#include <unistd.h>       /* for close() */
#include <netdb.h>
#include <errno.h>
#include <sys/wait.h>
#include <signal.h>
#define RCVBUFSIZE 32     /* Size of receive buffer */

void DieWithError(char *errorMessage);    /* Error handling function */
int ftpSendFile(char * buf, char * host, int port);
int ftpRecvResponse(int sock, char * buf);
int ftpNewCmd(int Sock, char * buf, char * cmd, char * param);
int ftpConvertAddr(char * buf, char * hostname, int * port);

/************************************
for collecting zoombie processes
*************************************/

void sigchld_handler(int s)
{
    while(waitpid(-1, NULL, WNOHANG) > 0);
}

int main(int argc, char *argv[])
{
    int sock, clntSock;																/*  Socket descriptor */
    //int dataSock;															/* Data sockeet Descriptor*/
    int i;
	int processID;
    struct sockaddr_in ftpServAddr;											/*  server address */
    struct hostent *hp;
    unsigned short ftpServPort;												/*  server port */
    char *servIP;															/*  Server IP address */
    char *username;															/* User Name for ftp server */
    char *pwd;																/* Password for connecting to ftp server*/
    char *fileName;															/*  FileName to get from the server */
    char *command;
    char *file;
    char *p;
    char *c;
	char *path;
	int count;
    char echoBuffer[RCVBUFSIZE];											/* Buffer for echo string */
    unsigned int echoStringLen;												/* Length of string to echo */
    int bytesRcvd, totalBytesRcvd;											/* Bytes read in single recv()*/
    ftpServPort = 21;
    char tmpHost[100];
    int tmpPort;
    char buf[5120];
     unsigned int PORTBUFFER;
     char * hostname;
	 servIP = argv[1] ;	/* First arg' server IP address */				

      /* Second arg' Username */
	  username = argv[2];
      													/* Third arg' Password */
	  pwd =  argv[3];
      printf("Creating Socket");
      
       struct sigaction sa; /* deal with signals from dying children! */
	   int yes = 1;
//int x = argc;
 // fprintf(stderr, "number of arguments passed %i x");

	  if (argc< 4) /* Test for correct number of arguments */
		{
			fprintf(stderr, "Usage: %s <Server IP> <UserName> <Password> <File-to-download> \n",
			argv[0]);
			exit(1);
		}
		//file = argv[4];
		//path = argv[5];
	    //int x;
            //for(x=1;x<(argc-3);x++)
             // {
	//	fileName = argv[3+x];
                //printf(fileName);
         //      }
       gethostname(hostname, PORTBUFFER);
     // if ((hp = gethostbyname(hostname)) == 0) {
      //perror("gethostbyname");
      //return -1;
   //}
	/* Create a reliable, stream socket using TCP */
	if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
     	 DieWithError(" socket () failed") ;

/* Construct the server address structure */
	memset(&ftpServAddr, 0, sizeof(ftpServAddr));							/* Zero out structure */
	ftpServAddr.sin_family         = AF_INET;								/* Internet address family */
	ftpServAddr.sin_addr.s_addr 	= inet_addr(servIP);					/* Server IP address */
	ftpServAddr.sin_port           = htons(ftpServPort);					/* Server port */

/* Establish the connection to the ftp server */
        if (connect(sock, (struct sockaddr *) &ftpServAddr, sizeof(ftpServAddr)) < 0)
           DieWithError(" connect () failed") ;
        else
	  printf("Connection Successful");

	//sleep(1);
	if(ftpRecvResponse(sock,buf)==1) 
	 {
          printf("Reached Here");
	  if(strncmp(buf,"220",3)==0) 
	   {
	    printf("Sending UserName");
	    printf(username);
	    if(ftpNewCmd(sock,buf,"USER",username)==1);
	     {
	      if(ftpRecvResponse(sock, buf) == 1)
  	       {
 	        if(strncmp(buf,"331",3)==0)
	         {
	  	       printf("Sending Password");
	           if(ftpNewCmd(sock, buf, "PASS", pwd) == 1)
 	            {
  	             if(ftpRecvResponse(sock, buf) == 1)
  	              {
   	               if(strncmp(buf, "230",3)==0)
    	               {
			   
			    for(i=1; i<(argc-3);i++)
			    {
				fileName = argv[3+i];
				if ((processID = fork()) < 0)
				{
				 DieWithError("HERE");
				 }
				else if(processID == 0)//this is the child
				 {
                                   if(ftpNewCmd(sock, buf, "PASV", "") == 1)
			           {
                                     if(ftpRecvResponse(sock, buf) == 1)
      	       		             {
       		             	      if(strncmp(buf, "227",3)==0)
        	              	      {
					ftpConvertAddr(buf,tmpHost,&tmpPort);
					if(ftpNewCmd(sock,buf,"RETR",fileName)==1)
					{
					 
					 ftpSendFile(fileName,tmpHost,tmpPort);
					 if(ftpRecvResponse(sock,buf)==1)
					 {
					  if(strncmp(buf,"150",3)==0)
					  {
					   if(ftpRecvResponse(sock, buf)==1)
					   {
                                            printf("\nReceive Response\n");
					   if(strncmp(buf,"226",3)==0)
					   {
					     printf("Transfer Completed");
					    //close(sock);
  					   //exit(0);
					   }
        	 			  }
       				         }
      	      			        }
     	    			       }
	   			      }
	  			     }
	 			    }
				   }
				else //this is the parent process
				 {
				   	/* Signal handler stuff */
			   		sa.sa_handler = sigchld_handler;
			   		/* reap all dead processes */
			   		sigemptyset( &sa.sa_mask);
			   		sa.sa_flags = SA_RESTART;
			   		if( sigaction( SIGCHLD, &sa, NULL) == -1)
			   		 {
			     		  perror( "Server sigaction");exit( 1);
			    		  }
				   }
				  }	//ftpSendFile(buf, "saraswati", 20);
 			         } 	//close(sock);
  			        }	//exit(0);
			       }
		              }
			     }
			    }
			   }
			  }	
/* ToDo: Put Code for writing file stats(size, name, time taken to download etc)*/
	//wait();
	close(sock);
  	exit(0);
}
int ftpSendFile(char * buf, char * host, int port) {
   int sd;
   struct sockaddr_in pin;
   struct hostent *hp;
   char * FileName;
   FileName = buf;
   if ((hp = gethostbyname(host)) == 0) {
      perror("gethostbyname");
      return -1;
   }
   memset(&pin, 0, sizeof(pin));
   pin.sin_family = AF_INET;
   pin.sin_addr.s_addr = ((struct in_addr *)(hp->h_addr))->s_addr;
   pin.sin_port = htons(port);
   if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
      perror("socket");
      return -1;
   }
   if (connect(sd,(struct sockaddr *)  &pin, sizeof(pin)) == -1) {
      perror("connect");
      return -1;
   }
   if(send(sd, buf, strlen(buf), 0) == -1) {
      perror("send");
      return -1;
   }
   	FILE *fd;
	char buff[4096];
	buff[4095] = '\0';

  	int n_bytes;
	int n_recv=0;
        printf("\n**********FileName**********\n");
        printf(FileName);
        printf("***********END***************\n");
	fd = fopen(FileName, "wb");
		
		if (fd == NULL) {
		//if (verbose) {
		printf("--[ Error: Unable to open '%s' in ftp_get function\n", FileName);
		//}

		//free(buffer);
		
		return -1;
		}

	//time(&start);

	while (1) {

		//usleep(150);
		n_recv = recv(sd, buff, 4094, 0);
		n_bytes = fwrite(buff, sizeof(char), n_recv, fd);
		
		if (n_recv == 0) {
			break;
		}

		n_recv = 0;

		memset(buff, 0x0, n_bytes);
		
		}

	
	fclose(fd);
printf("closing client socket");
   close(sd); /*//close the socket*/
   return 0;
}
int ftpRecvResponse(int Sock, char * buf) {
   int i;

   if (recv(Sock, buf, 1024, 0) == -1) {//receive the data
      perror("recv");
      return 0;;
   }
   for(i=(strlen(buf) - 1);i>0;i--) {
      if(buf[i]=='.' || buf[i]=='\r') { 
         buf[i+1]='\0';
         break;
      }
   }
   printf("%s\n",buf); //print response to the screen
   return 1;
}




int ftpNewCmd(int Sock, char * buf, char * cmd, char * param) {
   strcpy(buf,cmd);
   if(strlen(param) > 0) {
      strcat(buf," ");
      strcat(buf,param);
   }
   strcat(buf,"\r\n");
   printf("*%s",buf); //print the cmd to the screen
   if(send(Sock, buf, strlen(buf), 0) == -1) {
      perror("send");
      return 0;
   }
   //clear the buffer
//fflush(buf);
   return 1;
}

int ftpConvertAddr(char * buf, char * hostname, int * port) {
   unsigned int i,t=0;
   int flag=0,decCtr=0,tport1,tport2;
   char tmpPort[6];
   //example data in quotes below:
   //"227 Listening on (149,122,52,162,4,20)"
   //4 * 256 + 20 = 1044
   for(i=0;i<strlen(buf);i++) {
      if(buf[i]=='(') {
         flag = 1;
         i++;
      }
      if(buf[i]==')') {
         hostname[t]='\0';
         break;
      }
      if(flag==1) {
         if(buf[i] != ',') {
            hostname[t]=buf[i];
            t++;
         } else {
            hostname[t]='.';
            t++;
         }
      }
   }
   t=0;
   for(i=0;i<strlen(hostname);i++) {
      if(hostname[i]=='.')
         decCtr++;
      if(decCtr==4 && hostname[i]!='.') {
         tmpPort[t]=hostname[i];
         t++;
         if(hostname[i+1]=='.') {
            tmpPort[t]='\0';
            tport1=atoi(tmpPort);
            t=0;
         }
      }
      if(decCtr==5 && hostname[i]!='.') { 
         tmpPort[t]=hostname[i];
         t++;
         if(hostname[i+1]=='\0') {
            tmpPort[t]='\0';
            tport2=atoi(tmpPort);
            t=0;
         }
      }
   }
   *port = tport1 * 256 + tport2;
   decCtr=0;
   for(i=0;i<strlen(hostname);i++) {
      if(hostname[i]=='.') {
         decCtr++;
      }
      if(decCtr>3)
         hostname[i]='\0';
   }
   return 0;
}