⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ftp_operation.c

📁 一个LINUX下的服务器的小程序.可供学习.
💻 C
字号:
#include <errno.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include <sys/select.h>
#include <sys/socket.h>
#include "symbol_table.h"
#include "miniFTP.h"
#include "file_operation.h"
#include <stdio.h>

#define IP_LEN  16
static int ftp_open(int ftp_port) ;
static int ftp_ignore_sigpipe(void) ;
static int ftp_accept(int socket_fd) ;
static void handle_client_cmd(void) ;
//static void addr2name(struct in_addr addr) ;

extern void parse_cmd(char * buf) ;
extern struct user_env user_env;
extern struct run_env run_env;


int r_close(int fd)
{
	int state;
	while ((state = close(fd)) == -1 && errno == EINTR) {
		continue;
	}
	return state;
}



void start_ftp_server(void){
        write_log("[DEBUG_LOG] ---------->start_ftp_server begin. [%s]\n", _timestamp()) ;
	int socket_fd = -1;
	int connect_fd = -1 ;
	pid_t child_pid = -1;

	#ifdef  DEBUG
	run_env.ftp_port = 1999 ;
	#endif

	if((socket_fd = ftp_open(run_env.ftp_port)) == FTP_OPT_FAIL){
		write_log("[ERR_LOG] ftp_open error.\n");
		exit(1) ;
	}

	while(1){
		if((connect_fd = ftp_accept(socket_fd)) == FTP_OPT_FAIL){
			write_log("[ERR_LOG] ftp_accept error.\n") ;
			if(r_close(socket_fd) == FTP_OPT_FAIL){
				write_log("[ERR_LOG] close socket_fd error.") ;
			}
			exit(1) ;
		}

		write_log("[INFO_LOG] user connect_fd = %d\n", connect_fd) ;
		user_env.connect_fd = connect_fd ;

		#ifdef DEBUG
		write_log("[INFO_LOG] run to fork.\n") ;
		#endif

		signal(SIGCLD,SIG_IGN) ;

		if((child_pid = fork()) == -1){
			write_log("[ERR_LOG] fork child proces error.\n") ;
		}else if(child_pid){ /*parent process.*/
			if(r_close(user_env.connect_fd) == FTP_OPT_FAIL){
				write_log("[ERR_LOG] close child connect_fd error.\n") ;
			}
			continue ;
		}else if(child_pid == 0){ /*child*/
			if(r_close(socket_fd) == FTP_OPT_FAIL){
				write_log("[ERR_LOG]close parent listen socket error.\n") ;
			}
			
			handle_client_cmd() ;

			if(r_close(user_env.connect_fd) == FTP_OPT_FAIL){
				write_log("[ERR_LOG]close user connect_fd error.\n");
			}
			exit(0) ;
		}
		
	}
	
	
}


static int ftp_open(int ftp_port){	write_log("[DEBUG_LOG] ---------->ftp_open begin. ftp_port = %d [%s]\n", ftp_port, _timestamp()) ;
	int error ;
	struct sockaddr_in server_addr ;
	bzero((char*) &server_addr,sizeof(server_addr));
	int socket_fd ;
	int true = 1 ;

	//if((ftp_ignore_sigpipe() == -1) ||
		if((socket_fd = socket(AF_INET,SOCK_STREAM,0)) == FTP_OPT_FAIL){
		write_log("[ERR_LOG] socket error in ftp_open.\n") ;
		//perror("socket error\n") ;

		if(errno == EPROTONOSUPPORT ){
			write_log("[ERR_LOG] the protocal type or the specified protocal is not supported in the system.\n") ;
			//perror("the protocal type or the specified protocal is not supported in the system.") ;
		}else if(errno == ENFILE ){
			write_log("[ERR_LOG] no enough memory to create the new socket.\n") ;
			//perror("no enough memory to create the new socket.") ;
		}else if(errno == EMFILE ){
			write_log("[ERR_LOG] new socket cannot be create due to the process table overflow.\n") ;
			//perror("new socket cannot be create due to the process table overflow.") ;
		}else if(errno == EINVAL){
			write_log("[ERR_LOG] These parms are invalid.\n") ;
			//perror("These parms are invalid.") ;
		}else{
			write_log("[ERR_LOG] no enough memory.\n") ;
			//perror("no enough memory.") ;
		}

		write_log("[ERR_LOG] ftp_open error is socket or ftp_ignore_sigpipe.[%s]\n", _timestamp()) ;
		return FTP_OPT_FAIL ;
	}

	/**
  	 if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&true,sizeof(true)) == -1) {
      	 	error = errno;
      		while ((close(socket_fd) == -1) && (errno == EINTR)); 
      		errno = error;
		write_log("[ERR_LOG] ftp_open error is setsockopt.[%s]\n", _timestamp()) ;
      		return FTP_OPT_FAIL;
   	}
	**/
	 server_addr.sin_family = AF_INET ;
	 server_addr.sin_addr.s_addr = htonl(INADDR_ANY) ;
	 server_addr.sin_port = htons((short)ftp_port) ;

	 if((bind(socket_fd,(struct sockaddr *)&server_addr, sizeof(server_addr))) == FTP_OPT_FAIL){
	 	//perror("bind error.") ;
		write_log("[ERR_LOG] bind error in ftp_open.\n") ;
		if(errno == EADDRINUSE){
			write_log("[ERR_LOG] The given address is already in use.\n") ;
			//perror("The given address is already in use.\n") ;
		}else if(errno ==EACCES){
			write_log("[ERR_LOG] The address is protected.\n") ;
			//perror("The address is protected.\n");
		}

		if(r_close(socket_fd) == FTP_OPT_FAIL){
			write_log("[ERR_LOG] close socket_fd error.\n") ;
			//perror("close socket_fd error\n") ;
		}
		
		write_log("[ERR_LOG] ftp_open error is bind.[%s]\n", _timestamp()) ;
		return FTP_OPT_FAIL ;
	 }

	 if((listen(socket_fd,run_env.backlog)) == FTP_OPT_FAIL){
	 	//perror("listen error.") ;
		write_log("[ERR_LOG] listen error in ftp_open.\n") ;

		if(errno == EADDRINUSE){
			write_log("[ERR_LOG] Another socket is already listening on the same port.\n") ;
			//perror("Another socket is already listening on the same port.") ;
		}
		write_log("[ERR_LOG] ftp_open error is listen.[%s]\n", _timestamp()) ;
		return FTP_OPT_FAIL ;
	 }

	write_log("[DEBUG_LOG] <----------ftp_open end. socket_fd = %d [%s]\n", socket_fd, _timestamp()) ;
	 return socket_fd ;
	
}


/*
 *                           ftp_ignore_sigpipe
 * Ignore SIGPIPE if the default action is in effect.
 *
 * returns: 0 if successful
 *          -1 on error and sets errno
 */
static int ftp_ignore_sigpipe() {
   struct sigaction act;

   if (sigaction(SIGPIPE, (struct sigaction *)NULL, &act) == -1)
      return -1;
   if (act.sa_handler == SIG_DFL) {
      act.sa_handler = SIG_IGN;
      if (sigaction(SIGPIPE, &act, (struct sigaction *)NULL) == -1)
         return -1;
   }   
   return 0;
}

static int ftp_accept(int socket_fd) {
	write_log("[DEBUG_LOG] ---------->ftp_accept begin. socket_fd = %d [%s]\n", socket_fd, _timestamp()) ;
	printf("the listen socket_fd = %d\n", socket_fd) ;
	//write_log("ftp_accept begin.",1) ;
	socklen_t len = sizeof(struct sockaddr_in) ;
	int connect_fd ;
	char *ipstr ;
	char add[IP_LEN] ;
	struct sockaddr_in client_address ;
	for(;;){
		if((connect_fd = accept(socket_fd,(struct sockaddr *)(&client_address),&len)) == -1 &&(errno==EINTR) ){			continue ;
		}		if(connect_fd == -1){
			//fprintf(stderr,"accept error, errno is %d\n",errno) ;
			if(errno == ECONNABORTED){
				write_log("[ERR_LOG] A connection has been aborted.\n") ;
				//perror("A connection has been aborted.\n") ;
			}else if(errno == EPERM){
				write_log("[ERR_LOG] Firewall rules forbid connection.\n") ;
				//perror("Firewall rules forbid connection.\n") ;
			}else if(errno == ENFILE){
				write_log("[ERR_LOG] The system limit on the total numbers of open files has been reached.\n") ;
				//perror("The system limit on the total numbers of open files has been reached\n") ;
			}else if(errno == EINTR){
				
			}
		}

		break ;
		
	}

	//addr2name(client_address.sin_addr) ;

	ipstr = inet_ntoa(client_address.sin_addr) ;
	//if((user_env.client_ip =malloc(sizeof(char)*(strlen(add)+1))) != NULL ){
	//	strcpy(user_env.client_ip,ipstr) ;
	//}else{
	//	user_env.client_ip = NULL ;
	//}
        printf("the connect_fd = %d, ipstr = %s\n",connect_fd, ipstr) ;
	write_log("[DEBUG_LOG] <----------ftp_accept end, connect_fd = %d. [%s]\n",connect_fd,  _timestamp()) ;
	return connect_fd ;
	
}



static void handle_client_cmd(){
	write_log("[DEBUG_LOG] ---------->handle_client_cmd begin.[%s]\n", _timestamp()) ;
	int read_cnt ;
	int write_cnt ;
	char read_buf[BUF_LEN] ;
	int banner_len = strlen(run_env.welcome_banner) + 8 ;
	char welcome_msg[banner_len] ;

	snprintf(welcome_msg,banner_len,"220 %s\r\n",run_env.welcome_banner ) ;

	if((write_cnt = write(user_env.connect_fd,welcome_msg,strlen(welcome_msg))) == -1){
		write_log("write error.", 0);
		exit(errno) ;
	}

	while(1){
		if((read_cnt = read(user_env.connect_fd,read_buf,BUF_LEN)) <= 0){
			continue ;
		}

		parse_cmd(read_buf) ;
	}
	write_log("[DEBUG_LOG] <----------handle_client_cmd end. [%s]\n", _timestamp()) ;
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -