www.pudn.com > src.rar > client.c


#include  
#include  
#include  
#include  
#include  
 
//definations 
#define CRLF "\r\n" 
#define CALL_RETURN(a)  if ( a == -1) return -1;  
#define COMMAND_COUNT 	13 
#define COMMAND_LENGTH 	200 
#define BUFFER_LENGTH 	512 
 
//functions 
int ftp_hallo(); 
int ftp_conn(char *, int); 
int ftp_send_command(char *, int); 
int ftp_recv_reply(char *, int ); 
int ftp_user(char *username); 
int ftp_port(); 
int ftp_list(); 
int ftp_start_data_transfer(); 
int ftp_close_data_transfer(); 
int ftp_prompt(); 
int ftp_bye(); 
int ftp_help(char *); 
int ftp_pwd(); 
int ftp_send(char *, char *); 
 
enum { 
	com_conn,com_user,com_pass,com_send,com_retr,com_list, 
	com_cwd,com_pwd,com_quit,com_bye,com_pasv,com_port,com_help 
}ftp_command; 
 
char *ftp_symbol[] = 
{ 
	"connect","user","pass","put","get","dir","cd","pwd","quit","bye","pasv","port","help" 
}; 
 
char command[1000], *command_param; 
 
 
int sock,data_sock,port_sock; 
char pasv_addr[40]; 
int pasv_port; 
 
//type defines 
typedef enum{ 
	false,true 
}bool; 
bool running; 
bool connecting; 
 
enum{ 
	data_mode_pasv,data_mode_port 
} ftp_data_mode; 
 
 
int main(int argc,char *argv[]) 
{ 
	ftp_hallo();	 
	if(argc>1) 
	{ 
		int port; 
		if(argc>2) 
			sscanf(argv[2],"%d",&port); 
		else 
			port = 21; 
		 
		if( ftp_conn(argv[1],port) == 0 ) 
		{ 
			connecting = true; 
			ftp_user("anonymous"); 
			ftp_pass("anonymous"); 
			ftp_port(); 
			ftp_list(); 
		} 
	} 
	while(running) 
	{ 
		if ( ftp_prompt()==0 ) 
		switch(ftp_command) 
		{ 
			case com_conn: 
				{ 
					char addr[100]; 
					int port; 
					if( connecting ) 
					{ 
						printf("[ERROR]:Already connected!!\n"); 
						break; 
					} 
					sscanf(command_param,"%s %d",addr,&port); 
					if ( ftp_conn(addr,port) == 0 ) 
					{ 
						if( ftp_user("anonymous") !=0 ) 
							break; 
						if( ftp_pass("anonymous") != 0 ) 
							break; 
						if ( ftp_port() != 0 ) 
							break; 
						ftp_list(); 
					} 
					break; 
				} 
			case com_user: 
				{ 
					char username[100]; 
					sscanf(command_param," %[^\r\n]",username); 
					ftp_user(username); 
					break; 
				} 
			case com_pass: 
				{ 
					char password[100]; 
					sscanf(command_param," %[^\r\n]",password); 
					ftp_pass(password); 
					break; 
				} 
			case com_send: 
				{ 
					char rname[100],lname[100]; 
					int count = sscanf(command_param," %s %[^\r\n]",lname,rname); 
					if(count == 0)  
					{ 
						printf("[ERROR]:Local file not specified!!\n"); 
						break; 
					} 
					if(count == 1) 
						strcpy(rname,lname); 
					 
					if( ftp_data_mode == data_mode_pasv)  
						ftp_pasv(); 
					else 
						ftp_port(); 
					 
					ftp_send(lname,rname); 
					break; 
				} 
			case com_retr: 
				{ 
					char rname[100],lname[100]; 
					int count = sscanf(command_param," %s %[^\r\n]",rname,lname); 
					if(count == 0)  
					{ 
						printf("[ERROR]:Remote file not specified!!\n"); 
						break; 
					}	        
					if(count == 1) 
						strcpy(lname,rname); 
 
					if( ftp_data_mode == data_mode_pasv)  
						ftp_pasv(); 
					else 
						ftp_port(); 
					ftp_retr(rname,lname); 
					break; 
				} 
			case com_list: 
				{ 
					if( ftp_data_mode == data_mode_pasv)  
							ftp_pasv(); 
					else 
							ftp_port();					 
					ftp_list(); 
					break; 
				} 
			case com_cwd: 
				{ 
					char path[300]; 
					sscanf(command_param," %[^\r\n]",path); 
					ftp_cwd(path); 
					break; 
				} 
			case com_pwd: 
				{ 
					ftp_pwd(); 
					break; 
				} 
			case com_quit: 
				{ 
					if( !connecting ) 
					{ 
						printf("[ERROR]:Not connected yet!!\n"); 
						break; 
					} 
					if ( ftp_quit() == 0 ) 
						connecting = false; 
					break; 
				} 
			case com_bye: 
				{ 
					ftp_bye(); 
					break; 
				} 
			case com_pasv: 
				{ 
					ftp_pasv(); 
					break; 
				} 
			case com_port: 
				{ 
					ftp_port(); 
					break; 
				} 
			case com_help: 
				{ 
					char command_name[100]; 
					sscanf(command_param," %[^\r\n]",command_name); 
					ftp_help(command_name); 
				} 
			default: 
				break; 
		}; 
	} 
} 
 
int ftp_user(char *username)//USER XXX 
{ 
	char cmd[COMMAND_LENGTH]; 
	sprintf(cmd,"USER %s",username); 
	CALL_RETURN(ftp_send_command(cmd,strlen(cmd))); 
	CALL_RETURN(ftp_recv_reply(cmd,COMMAND_LENGTH)); 
	printf(cmd); 
	return 0; 
} 
int ftp_pass(char *password) 
{ 
	char cmd[COMMAND_LENGTH]; 
	sprintf(cmd,"PASS %s",password); 
	CALL_RETURN(ftp_send_command(cmd,strlen(cmd))); 
	CALL_RETURN(ftp_recv_reply(cmd,COMMAND_LENGTH)); 
	printf(cmd); 
	return 0; 
} 
 
int ftp_list() 
{ 
	char cmd[COMMAND_LENGTH]; 
	char buffer[BUFFER_LENGTH]; 
	int  len; 
	CALL_RETURN(ftp_send_command("LIST",4)); 
 
	if( ftp_data_mode == data_mode_port ) 
	{ 
		CALL_RETURN(ftp_recv_reply(cmd,sizeof(cmd))); 
		printf(cmd); 
		if(	strncmp(cmd,"150",3)!=0 ) 
			return -1; 
	} 
	 
	if( ftp_start_data_transfer() == 0 ) 
	{ 
		if (ftp_data_mode == data_mode_pasv) 
		{ 
			CALL_RETURN(ftp_recv_reply(cmd,sizeof(cmd))); 
			printf(cmd); 
			if(	strncmp(cmd,"150",3)!=0 ) 
				return -1; 
		} 
		while( (len=read(data_sock,buffer,sizeof(buffer)-1)) > 0 ) 
		{ 
			buffer[len]='\0'; 
			printf(buffer); 
		} 
	} 
	else 
		printf("[ERROR]:Fail to start data transfer!!\n"); 
	 
	CALL_RETURN(ftp_recv_reply(cmd,sizeof(cmd))); 
	printf(cmd); 
	ftp_close_data_transfer(); 
	return 0; 
} 
int ftp_port() 
{ 
	int i,length,port; 
	char cmd[COMMAND_LENGTH]; 
	struct sockaddr_in server; 
 
	port_sock=socket(AF_INET,SOCK_STREAM,0); 
	if (port_sock<0) 
	{ 
		printf("[FAIL]:Opening data socket failed!!\n"); 
		return -1; 
	} 
	server.sin_family=AF_INET; 
	server.sin_addr.s_addr=INADDR_ANY; 
	server.sin_port=0; 
	if (bind(port_sock,(struct sockaddr *)&server,sizeof(server))<0) 
	{ 
		printf("[FAIL]:Binding stream socket failed!!\n"); 
		return -1; 
	} 
	length=sizeof(server); 
	if ( getsockname(port_sock,(struct sockaddr *)&server,&length)!=0 ) 
	{ 
		printf("[FAIL]:Getting data socket port failed!!\n"); 
		return -1; 
	} 
	port = ntohs(server.sin_port); 
	length=sizeof(server);	 
	if ( getsockname(sock,(struct sockaddr *)&server,&length)!=0 ) 
	{ 
		printf("[FAIL]:Getting socket name failed!!\n"); 
		return -1; 
	} 
	sprintf(cmd,"PORT %s,%d,%d",inet_ntoa(server.sin_addr),port/256,port%256); 
	length = strlen(cmd); 
	printf(cmd); 
	for(i=0;ih_addr, hp->h_length); 
	if (connect(sock,(struct sockaddr *)&server,sizeof server)<0) 
	{ 
		printf("[FAIL]:Connecting stream socket failed!!\n"); 
		return -1; 
	} 
	printf("[SUCCEED]:Connected to host!!\n"); 
	{ 
		char cmd[COMMAND_LENGTH]; 
		CALL_RETURN(ftp_recv_reply(cmd,COMMAND_LENGTH)); 
		printf(cmd); 
	} 
 
	connecting = true; 
	 
	return 0; 
} 
 
 
int ftp_hallo() 
{ 
	 printf("\t\t********* ftp client **********. \n"); 
	 running = true; 
	 connecting = false; 
	 sock = 0; 
	 port_sock = 0; 
	 ftp_data_mode = data_mode_port; 
	 return 0; 
} 
 
int ftp_send_command(char *command, int len) 
{ 
	printf("[OPRATE]:Sending command %s.\n",command); 
 
        if (write(sock,command, len) == -1) 
	{ 
		printf("[FAIL]:Sending ftp command failed!!\n"); 
		//fprintf(stderr,"in command %s.\n",command); 
		return -1; 
	} 
        if ( write(sock,CRLF,2) == -1 ) 
	{ 
		printf("[FAIL]:Sending ftp command CRLF failed!!\n"); 
		return -1; 
	} 
        return 0; 
}  
 
int ftp_recv_reply(char *buffer, int len) 
{ 
	int i; 
	for(i=0;ih_addr, hp->h_length); 
				printf("[OPRATE]:Establishing data connection to %s:%d...\n",pasv_addr,pasv_port); 
			        if (connect(data_sock,(struct sockaddr *)&server,sizeof server)<0) 
			        { 
			                printf("[FAIL]:Connecting data socket failed!!\n"); 
					return -1; 
				} 
				printf("[SUCCEED]:Data connection established!!\n"); 
				break; 
			} 
		case data_mode_port: 
			{ 
				printf("[OPRATE]:Accepting data connection...\n"); 
				data_sock = accept(port_sock,(struct sockaddr*)0,(int*)0); 
				if(data_sock == -1) 
				{ 
					printf("[FAIL]:Accept data socket!!\n"); 
					return -1; 
				} 
				break; 
			} 
	} 
	return 0; 
} 
 
int ftp_close_data_transfer() 
{ 
	close(data_sock); 
	data_sock = 0; 
} 
int ftp_prompt() 
{ 
	int i; 
 
	printf("yuhuijia's FTP>"); 
	fgets(command,sizeof(command),stdin); 
	 
	// find the corresponding command with the command string 
	for(i=0;i0 ) 
			{ 
				write(data_sock,buffer,len); 
			} 
        } 
        else 
                printf("[FAIL]:Fail to start data transfer!!\n"); 
	fclose(file); 
	ftp_close_data_transfer(); 
	CALL_RETURN(ftp_recv_reply(cmd,sizeof(cmd))); 
	printf(cmd); 
	// should be 226 reply 
	return 0; 
} 
 
 
int ftp_retr(char *filename, char *localname) 
{ 
    char cmd[200]; 
    char buffer[512]; 
    int  len; 
    FILE *file; 
    file = fopen(localname,"w+"); 
    if( file == NULL ) 
    { 
        printf("open local file"); 
	    return -1; 
	}	 
	sprintf(cmd,"RETR %s",filename); 
	CALL_RETURN(ftp_send_command(cmd,strlen(cmd))); 
	if( ftp_data_mode == data_mode_port ) 
	{        
		CALL_RETURN(ftp_recv_reply(cmd,sizeof(cmd))); 
		printf(cmd); 
		if(	strncmp(cmd,"150",3)!=0 ) 
			return -1; 
		// should be 150 reply 
	} 
	if( ftp_start_data_transfer() == 0 ) 
	{        
		if (ftp_data_mode == data_mode_pasv) 
		{        
			CALL_RETURN(ftp_recv_reply(cmd,sizeof(cmd))); 
			printf(cmd); 
			if(	strncmp(cmd,"150",3)!=0 ) 
				return -1; 
			// should be 150 reply 
		} 
		while( (len=read(data_sock,buffer,sizeof(buffer))) >0 ) 
		{        
			fwrite(buffer,1,len,file); 
		} 
		printf("[SUCCEED]:End of sending!!\n"); 
	}        
	else 
	printf("[FAIL]:Fail to start data transfer!!\n"); 
	fclose(file); 
	ftp_close_data_transfer(); 
	CALL_RETURN(ftp_recv_reply(cmd,sizeof(cmd))); 
	printf(cmd); 
	//should be 226 reply 
	return 0; 
}