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;i h_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;i h_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;i 0 ) { 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; }