📄 command_fun.c
字号:
#include "extern.h"
/*-------------------------------------------------------*/
/*获取用户名称*/
int Cmd_USER(char *buf, char *send_msg)
{
int i;
int temp = 0;
strcpy(USER,buf+5);
//判断可登录用户配置文件是否有效
//ENABLE_USERLIST =1 表示有效
if(ENABLE_USERLIST == 1)
{
//验证可登录用户配置文件里面是否有相同的用户名称
for(i = 0; i<10; i++)
{
//进行比较,=0表示找到了
if(strcmp(USER, ENABLE_LOGIN_USER[i]) == 0)
{
temp =1;
break;
}
}
if(1 == temp)
{
Ftp_State_Return(send_msg, 331);
return 1;
}
else
{
Send_Message(CMD_SOCKFD, "530 Permission denied.\r\n", 24);
close(CMD_SOCKFD);
exit(0);
}
}
else
{
//系统目录下查看是否有相同的用户名
seteuid(0);
setegid(0);
struct spwd *spw=getspnam(USER);
if(spw == NULL)
{
//允许匿名登录
if(ENBALE_ANONYMOUS == 1)
{
//把匿名用户名称anonymous当作登录用户名
memset(USER, 0, 20);
strcpy(USER, "ftp");
Check_User(USER, PASSWORD, &UID, &GID, USER_DIR, 0);
seteuid(UID);
setegid(GID);
chdir(USER_DIR);
Ftp_State_Return(send_msg, 230);
return 1;
}
Send_Message(CMD_SOCKFD, "530 Permission denied.\r\n", 24);
return 0;
}
else
{
Ftp_State_Return(send_msg, 331);
return 1;
}
}
}
/*-------------------------------------------------------*/
/*获取密码,并进行验证*/
int Cmd_PASS(char *passwd, char *send_msg)
{
strcpy(PASSWORD,passwd+5);
//判断用户密码是否正确
if( Check_User(USER, PASSWORD, &UID, &GID, USER_DIR, 1) == 1)
{
//发送信息给客户端,提示登录成功,可以发送下个数据
//要返回给服务器的命令
Ftp_State_Return(send_msg, 230);
seteuid(UID);
setegid(GID);
chdir(USER_DIR);
return 1;
}
else
{
//发送信息,用户名或密码失败
Send_Message(CMD_SOCKFD, "530 Login incorrect\r\n", 21);
close(CMD_SOCKFD);
exit(0);
}
}
int Cmd_SYST(char *buf, char *send_msg)
{
Ftp_State_Return(send_msg, 215);
return 1;
}
int Cmd_FEAT(char *buf, char *send_msg)
{
Ftp_State_Return(send_msg, 500);
return 1;
}
int Cmd_REST(char *buf, char *send_msg)
{
char size[100];
memset(size, 0, 100);
strcpy(size, buf+5);
OFFSET = atoi(size);
sprintf(send_msg, "350 Restart position accepted (%s).\r\n", size);
Send_Message(CMD_SOCKFD, send_msg, strlen(send_msg));
return 0;
}
int Cmd_TYPE(char *buf, char *send_msg)
{
Ftp_State_Return(send_msg, 200);
return 1;
}
int Cmd_NOOP(char *buf, char *send_msg)
{
Send_Message(CMD_SOCKFD, "200 NOOP ok.\r\n", 14);
return 0;
}
/*-------------------------------------------------------*/
/*PORT模式,主动模式,服务器连接客户端*/
int Cmd_PORT(char *buf, char *send_msg)
{
int iret;
int port;
int len;
char ip[100];
struct sockaddr_in cli_addr;
char temp[100];
memset(temp, 0, 100);
memset(ip, 0, 100);
strcpy(temp, buf+5);
Get_Ip_Port(temp, ip, &port);
cli_addr.sin_family=AF_INET;
cli_addr.sin_addr.s_addr=inet_addr(ip);
cli_addr.sin_port=htons(port);
len = sizeof(cli_addr);
DATA_SOCKFD = socket(AF_INET, SOCK_STREAM, 0);
iret = connect(DATA_SOCKFD, (struct sockaddr *)(&cli_addr), len);
if (iret == -1)
{
perror("port error");
}
Send_Message(CMD_SOCKFD, "200 PORT command successful. Consider using PASV.\r\n", 51);
return 0;
}
/*-------------------------------------------------------*/
/*被动模式,创建监听窗口*/
int Cmd_PASV(char *buf, char *send_msg)
{
int len;
int port;
struct sockaddr_in address;
char temp[100];
memset(temp, 0, 100);
//创建监听窗口
if( ! (LISTEN_SOCKFD = Init_Socket(0, IP)) )
{
printf("LISTEN SOCKET INIT FAILED!");
exit(0);
}
len = sizeof(address);
getsockname(LISTEN_SOCKFD, (struct sockaddr *)&address, &len);
port = ntohs(address.sin_port);
if( listen(LISTEN_SOCKFD, 10) != 0 )
{
printf("LISTEN SOCKET LINSTEN FAIL!\n");
exit(0);
}
strcpy(temp, IP);
Ip_Change(temp);
sprintf(send_msg, "227 Entering Passive Mode (%s,%d,%d)\r\n", temp, (port>>8)&0xff, port&0xff);
Send_Message(CMD_SOCKFD, send_msg, strlen(send_msg));
while(1)
{
//接受连接
if( (DATA_SOCKFD = Accept_Connect(LISTEN_SOCKFD, &address)) == 0 )
{
continue;
}
break;
}
close(LISTEN_SOCKFD);
return 0;
}
/*-------------------------------------------------------*/
/*列出当前目录的详细信息*/
int Cmd_LIST(char *buf, char *send_msg)
{
char send[100];
char buffer[8000];
memset(buffer, 0, 8000);
//获取当前目录的详细信息,保存到BUFFER里
List(buffer, 8000);
//告诉客户端,要开始发送数据给它了
Ftp_State_Return(send, 150);
Send_Message(CMD_SOCKFD, send, strlen(send));
//用数据套接字发送数据给客户端
Send_Message(DATA_SOCKFD, buffer, strlen(buffer));
//告诉客户端,发送数据完毕
Ftp_State_Return(send, 226);
Send_Message(CMD_SOCKFD, send, strlen(send));
//关闭数据套接字和监听套接字
close(DATA_SOCKFD);
close(LISTEN_SOCKFD);
return 0;
}
/*-------------------------------------------------------*/
/*退出系统*/
int Cmd_QUIT(char *buf, char *send_msg)
{
Send_Message(CMD_SOCKFD, "221 退出\r\n", 10);
if(shmdt(share_memory) == -1)
{
printf("share_memory shmdt fail!\n");
}
close(SOCKFD);
close(CMD_SOCKFD);
exit(0);
}
/*-------------------------------------------------------*/
/*建立文件夹*/
int Cmd_MKD(char *buf, char *send_msg)
{
char path[100] = "/";
char buffer[100];
memset(ABSOLUTE_PATH, 0, 100);
memset(buffer, 0, 100);
strcpy(buffer, buf+4);
//建立文件夹
mkdir(buffer, 0777);
//获取当前路径
getcwd(ABSOLUTE_PATH, 100);
strcat(path, buffer);
strcat(ABSOLUTE_PATH, path);
sprintf(send_msg, "257 \"%s\" created\r\n", ABSOLUTE_PATH);
Send_Message(CMD_SOCKFD, send_msg, strlen(send_msg));
memset(path, 0, 100);
return 0;
}
/*-------------------------------------------------------*/
/*删除文件夹*/
int Cmd_RMD(char *buf, char *send_msg)
{
char file_name[100];
memset(file_name, 0, 100);
//把发过来要进去的文件名保存起来
strcpy(file_name,buf+4);
remove(file_name);
Send_Message(CMD_SOCKFD, "250 Remove directory operation successful\r\n", 43);
return 0;
}
/*-------------------------------------------------------*/
/*删除文件*/
int Cmd_DELE(char *buf, char *send_msg)
{
char file_name[100];
memset(file_name, 0, 100);
strcpy(file_name,buf+5);
remove(file_name);
Send_Message(CMD_SOCKFD, "250 Delete operation successful.\r\n", 34);
return 0;
}
/*-------------------------------------------------------*/
/*获取当前工作目录的绝对路径*/
int Cmd_PWD(char *buf, char *send_msg)
{
memset(ABSOLUTE_PATH, 0, 100);
getcwd(ABSOLUTE_PATH, 100);
sprintf(send_msg, "257 \"%s\"\r\n", ABSOLUTE_PATH);
Send_Message(CMD_SOCKFD, send_msg, strlen(send_msg));
return 0;
}
/*-------------------------------------------------------*/
/*到某个目录下*/
int Cmd_CWD(char *buf, char *send_msg)
{
char path[100] = "./";
char buffer[100];
memset(buffer, 0, 100);
//把发过来要进去的文件名保存起来
strcpy(buffer,buf+4);
//往上层目录
if(buffer[0] == '/')
{
//进行目录转换操作
if (chdir(buffer) != 0)
{
printf("chdir(buffer)(Cmd_CWD)-ERROR\n");
}
memset(ABSOLUTE_PATH, 0, 100);
getcwd(ABSOLUTE_PATH, 100);
memset(buffer, 0, 100);
memset(path, 0, 100);
Ftp_State_Return(send_msg, 250);
Send_Message(CMD_SOCKFD, send_msg, strlen(send_msg));
return 0;
}
//到下层目录
else
{
//进行目录转换操作
strcat(path, buffer);
if(chdir(path) != 0)
{
printf("chdir(path)(Cmd_CWD)-ERROR\n");
}
memset(path, 0, 100);
memset(buffer, 0, 100);
Ftp_State_Return(send_msg, 250);
Send_Message(CMD_SOCKFD, send_msg, strlen(send_msg));
return 0;
}
}
/*-------------------------------------------------------*/
/*返回上级目录*/
int Cmd_CDUP(char *buf, char *send_msg)
{
char path[100] = "..";
if (chdir(path) != 0)
{
printf("chdir[Cmd_CDUP]-ERROR\n");
}
memset(path, 0, 100);
Ftp_State_Return(send_msg, 250);
Send_Message(CMD_SOCKFD, send_msg, strlen(send_msg));
return 0;
}
/*-------------------------------------------------------*/
/*重命名,传入数据,要重命名的文件夹*/
int Cmd_RNFR(char *buf, char *send_msg)
{
memset(FILE_NAME, 0, 100);
strcpy(FILE_NAME,buf+5);
Send_Message(CMD_SOCKFD, "350 Ready for RNTO\r\n", 20);
return 0;
}
/*-------------------------------------------------------*/
/*重命名*/
int Cmd_RNTO(char *buf, char *send_msg)
{
char name[100];
memset(name, 0, 100);
strcpy(name, buf+5);
//进行重命名操作
rename(FILE_NAME, name);
Send_Message(CMD_SOCKFD, "250 Rename successful\r\n", 23);
return 0;
}
/*-------------------------------------------------------*/
/*下载文件,命名后面为要下载的文件名称*/
int Cmd_RETR(char *buf, char *send_msg)
{
struct stat st;
int fd = -1;
int byte,state;
char data[4096];
char file_name[100];
long int total_flux = 0;
time_t time1,time2;
memset(data, 0, 100);
memset(file_name, 0, 100);
strcpy(file_name, buf+5);
if( stat(file_name, &st) != 0 )
{
printf("Cmd_RETR-stat()-ERROR\n");
}
byte = st.st_size;
sprintf(send_msg, "150 Opening BINARY mode data connection for %s (%d bytes).\r\n", file_name, byte);
//把当前文件名称和大小发送个客户端
Send_Message(CMD_SOCKFD, send_msg, strlen(send_msg));
if( (fd = open(file_name, O_RDONLY)) < 0)
{
printf("Cmd_RETR--open-error\n");
}
//断点下载,如果OFFSET为0,就说明没文件
if( lseek(fd, OFFSET, SEEK_SET) == -1)
{
printf("Cmd_RETR lseek error\n");
}
time(&time1);
while (1)
{
if ( ( state = read(fd, data, sizeof(data)) ) < 0)
{
printf("Cmd_RETR read error\n");
break;
}
if (state == 0)
{
break;
}
//发送
Send_Message(DATA_SOCKFD, data, state);
total_flux += state;
time(&time2);
if( (time2 - time1) > 0)
{
if( ( (total_flux/1024)/(time2 - time1) ) > MIN_DOWNLOAD_SPEED)
{
usleep(100000);
}
}
share_memory->TOTAL_DOWNLOAD += state;
}
Send_Message(CMD_SOCKFD, "226 File send OK.\r\n", 19);
OFFSET = 0;
close(DATA_SOCKFD);
return 0;
}
/*-------------------------------------------------------*/
/*上传文件,命名后面为要上传的文件名称*/
int Cmd_STOR(char *buf, char *send_msg)
{
int fd = -1;
int byte,state,irecv;
char data[4096];
char file_name[100];
long int total_flux = 0;
time_t time1,time2;
memset(data, 0, 100);
memset(file_name, 0, 100);
strcpy(file_name, buf+5);
Send_Message(CMD_SOCKFD, "150 Ok to send data.\r\n", 22);
if( (fd = open(file_name, O_WRONLY|O_CREAT|O_TRUNC, 0777)) < 0 )
{
printf("Cmd_STOR--open-error\n");
}
if( lseek(fd, OFFSET, SEEK_SET) == -1)
{
printf("Cmd_STOR lseek error\n");
}
time(&time1);
while (1)
{
if ( (irecv=Recv_Message(DATA_SOCKFD, data, 4096)) <0 )
{
printf("Cmd_STOR Recv_Message NO_DATA\n");
break;
}
if( irecv == 0)
{
printf("Cmd_STOR Recv_Message TIMEOUT\n");
break;
}
if ( ( state = write(fd, data, irecv) ) < 0)
{
printf("Cmd_STOR write error\n");
break;
}
if (state == 0)
{
break;
}
total_flux += irecv;
time(&time2);
if( (time2 - time1) > 0)
{
if( ( (total_flux/1024)/(time2 - time1) ) > MAX_UPLOAD_SPEED)
{
usleep(200000);
}
}
share_memory->TOTAL_UPLOAD +=irecv;
}
Send_Message(CMD_SOCKFD, "226 File receive OK.\r\n", 22);
OFFSET = 0;
close(fd);
close(DATA_SOCKFD);
return 0;
}
/*-------------------------------------------------------*/
/*已追加的方式上传*/
int Cmd_APPE(char *buf, char *send_msg)
{
int fd = -1;
int state,irecv;
char data[4096];
char file_name[100];
long int total_flux = 0;
time_t time1,time2;
memset(data, 0, 100);
memset(file_name, 0, 100);
strcpy(file_name, buf+5);
Send_Message(CMD_SOCKFD, "150 Ok to send data.\r\n", 22);
if( (fd = open(file_name, O_WRONLY| O_APPEND)) < 0 )
{
printf("Cmd_APPE--open-error\n");
}
time(&time1);
while (1)
{
if ( (irecv=Recv_Message(DATA_SOCKFD, data, sizeof(data))) <0 )
{
printf("Cmd_APPE Recv_Message NO_DATA\n");
break;
}
if( irecv == 0)
{
printf("Cmd_APPE Recv_Message TIMEOUT\n");
break;
}
if ( ( state = write(fd, data, irecv)) < 0)
{
printf("Cmd_APPE write error\n");
break;
}
if (state == 0)
{
break;
}
total_flux += irecv;
time(&time2);
if( (time2 - time1) > 0)
{
if( ( (total_flux/1024)/(time2 - time1) ) > MAX_UPLOAD_SPEED)
{
usleep(100000);
}
}
share_memory->TOTAL_UPLOAD +=irecv;
}
Send_Message(CMD_SOCKFD, "226 File receive OK.\r\n", 22);
close(fd);
close(DATA_SOCKFD);
return 0;
}
int Cmd_HELP(char *buf, char *send_msg)
{
char msg[1024];
memset(msg, 0, 1024);
strcpy(msg, "214- The following commands are recognized (* => unimplemented).\r\n"\
"USER PASS SYST FEAT TYPE PASV LIST QUIT DELE\r\n"\
"CDUP RNFR RNTO STOR APPE PORT HELP PWD MKD \r\n"\
"RMD CWD XRMD XMKD XPWD SIZE ABOR \r\n"\
"214 Direct comments or bugs to bugs@bugs.com.\r\n");
Send_Message(CMD_SOCKFD, msg, strlen(msg));
return 0;
}
/*-------------------------------------------------------*/
/*获取指定文件的大小*/
int Cmd_SIZE(char *buf, char *send_msg)
{
char file_name[100];
struct stat st;
int size;
memset(file_name, 0, 100);
strcpy(file_name, buf+5);
if( stat(file_name, &st) == 0)
{
size = st.st_size;
sprintf(send_msg, "213 %s is %d bytes\r\n", file_name, size);
Send_Message(CMD_SOCKFD, send_msg, strlen(send_msg));
return 0;
}
//没有这个文件存在,
else
{
Send_Message(CMD_SOCKFD, "550 Could not get file size.\r\n", 30);
return 0;
}
}
/*-------------------------------------------------------*/
/*返回控制连接的状态,服务器上传下载了多少文件*/
int Cmd_STAT(char *buf, char *send_msg)
{
long int up;
long int down;
up = share_memory->TOTAL_UPLOAD/1024;
down = share_memory->TOTAL_DOWNLOAD/1024;
sprintf(send_msg, "总上传:%d KB.\r\n""总下载:%d KB.\r\n""当前控制连接正常\r\n""200 \r\n", up, down);
Send_Message(CMD_SOCKFD, send_msg, strlen(send_msg));
return 0;
}
/*-------------------------------------------------------*/
/*强行终止*/
int Cmd_ABOR(char *buf, char *send_msg)
{
Send_Message(CMD_SOCKFD, "强行终止\r\n", 10);
Send_Message(CMD_SOCKFD, "226 File receive OK.\r\n", 22);
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -