📄 ftppub.c
字号:
#include <string.h>
#include <stdio.h>
#include <stdarg.h> //这个头文件是为va_start跟 va_end函数
#include <sys/param.h> //PATH_MAX声明的地方
#include <unistd.h> //write函数的头文件
#include <pwd.h> //struct passwd这个声明要用的
#include <sys/types.h>
#include <shadow.h>//getspnam()
#include <stdlib.h>//atoi()函数
#include <ctype.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <signal.h>
#include <errno.h>
#include "ftppub.h"
#define SEND_BUFF 512
#define SEM_MAX 1
void Trim(char number1[]) //接受一个字符串,去除其前后空格
{
int j,len;
len=strlen(number1);
for(j=0;j<len;j++)//去前面空格
{
if(number1[j]!=' ')
break;
}
strcpy(number1,&number1[j]);
for(j=strlen(number1);j>0;j--)//q去后面空格
{
if(number1[j-1]!=' ')
{
number1[j]='\0';
break;
}
}
}
//服务端的响应函数
void Respond(int signal,char * message,...) //message
{
va_list ap;
char tmp[SEND_BUFF+1]={0};
char respond_msg[SEND_BUFF+1]={0};
va_start(ap,message);
vsprintf(tmp,message,ap);
va_end(ap);
sprintf(respond_msg,"%d %s\r\n",signal,tmp);
// printf("socket %d\n",connected_socket);
write(connected_socket,respond_msg,strlen(respond_msg));
// printf("发送响应内容 %s \n",respond_msg);
}
int Intercept_Command(char *cmd,char * msg)
{
char * p=0;
if(msg==NULL)
{
return -1;
}
if(strcmp(msg,"")==0)//接收到空消息的时候
{
return -1;
}
p=strchr(msg,' ');//查找空格,有存在返回空格的指针
if(p==NULL)
{
strcpy(cmd,msg);
//cmd[strlen(cmd)-2]='\0';
}
else
{
strncpy(cmd,msg,p-msg);
}
int i=0;
int len=strlen(cmd);
for(;i<len;i++)
{
cmd[i]=toupper(cmd[i]);
}
return 1;
}
int Intercept_Parameter(char *par,char *msg)//截取命令的参数
{
char * p=0;
if(msg==NULL)
{
return -1;
}
p=strchr(msg,' ');//查找空格,有存在返回空格的指针
if(p!=NULL)
{
strcpy(par,p+1);
}
else
{
memset(par,0,sizeof(*p));
}
// printf("参数的值是 %s\n",par);
return 1;
}
int Login(char * username,char *input_pwd)//验证用户名跟密码,符合条件下更改用户目录 返回帐号密码类型1正确,2匿名,-1错误
{
struct passwd *pw=NULL; // used for /etc/passwd 存放用户名,还有该 用户的路径
struct spwd *spw=NULL; // used for /etc/shadow 存放用户名的密码
char * real_passwd=NULL;
char tmp[15]={0};
if ((pw = getpwnam(username)) == NULL)//判断用户名是否存在
{
printf("用户名不存在Login incorrect.\n");
return -1;
}
//取得保存用户密码的结构体
spw=getspnam(username);
if (spw == NULL || (real_passwd = spw->sp_pwdp) == NULL) {
printf("无密码Login incorrect.\n");
return -1;
}
// 取得passwd的前12个字节作为种子
strncpy(tmp, real_passwd, 12);
// 判断输入的密码加密后是否与原密码相同
if (strcmp(real_passwd, crypt(input_pwd, tmp)) != 0)
{
// 密码错误
printf("密码错误Login incorrect.\n");
return -1;
}
// 密码正确,改变程序有效权限(有效权限也可理解为临时权限),即设置当前进程只能以这个用户的权限进行访问,及这个用户所在组的权限进行访问
setegid(pw->pw_gid);//要先改有效组然后再改有效用户
seteuid(pw->pw_uid);
if (pw->pw_dir) strncpy(path, pw->pw_dir,PATH_MAX);
else strcpy(path, "/");
chdir(path);
return 1;
}
int Anonymous_Login(char * username,char *input_pwd)//验证用户名跟密码,符合条件下更改用户目录 返回帐号密码类型1正确,2匿名,-1错误
{
struct passwd *pw=NULL; // used for /etc/passwd 存放用户名,还有该 用户的路径
//struct spwd *spw=NULL; // used for /etc/shadow 存放用户名的密码
// char * real_passwd=NULL;
// char tmp[15]={0};
if ((pw = getpwnam(username)) == NULL)//判断用户名是否存在
{
printf("用户名不存在Login incorrect.\n");
return -1;
}
//改变进程有效权限(有效权限也可理解为临时权限),即设置当前进程只能以这个用户的权限进行访问,及这个用户所在组的权限进行访问
setegid(pw->pw_gid);//要先改有效组然后再改有效用户
seteuid(pw->pw_uid);
/*
strncpy(path, pw->pw_dir,PATH_MAX);
strcpy(anonymous_dir, "/");
chdir(path);
*/
strncpy(anonymous_dir, pw->pw_dir,PATH_MAX);
strcpy(path, "/");
strcpy(cur_anonymous_dir,anonymous_dir);
chdir(cur_anonymous_dir);
return 1;
}
int separate_ip_port(char *parma,char *ip,int *port)//从字符串中分离出IP地址跟端口
{
int strlength=strlen(parma); //192,168,0,1,15,42
int i=0;
int count=0;//用来统计字符','的个数
//将字符串的所有','字符都替换成'.'
char hight_byte[4]={0};//存放端口的高字节
char low_byte[4]={0};
for(i=0;i<strlength;i++)
{
if(parma[i]==',')
{
parma[i]='.';
count++;
}
if(count==4)
{
strncpy(ip,parma,i);
strcpy(parma,parma+i+1);//把字符串后边的端口值移动到前边
break;
}
}
//取出端口值
strlength=strlen(parma);
for(i=0;i<strlength;i++)
{
if(parma[i]==',')
{
strncpy(hight_byte,parma,strlength-i-1);
strcpy(low_byte,parma+i+1);
break;
}
}
*port=atoi(hight_byte)*256+atoi(low_byte);
return 1;
}
//////////////////////////////////////////////////////////////////////////
//共享内存函数
int CreateShm()//创建一个共享内存
{
key_t key;
key = ftok(".", 'M');
if((g_shmid = shmget(key, sizeof(FLUXCTRL), IPC_CREAT|IPC_EXCL|0666)) == -1) //IPC_EXCL作用就是确保在共享内存存在时再去创建就失败了
{
// printf("Shared memory segment exists - opening as client\n");
if((g_shmid = shmget(key, sizeof(FLUXCTRL), 0)) == -1)
{
perror("shmget");
exit(1);
}
}
if((int)(g_segptr = (FLUXCTRL*)shmat(g_shmid,0,0)) == -1)//shmat第二个参数为NULL(即0)作用是让系统选择一个未使用的地址位置去附上共享内存段
{
perror("shmat");
exit(1);
}
memset(g_segptr,0,sizeof(*g_segptr));
return 1;
}
int Attach_Shm(int shmid)//将共享内存段附加到当前进程未使用的地址上去shared memory segment
{
if((int)(g_segptr = (FLUXCTRL*)shmat(shmid,0,0)) == -1)//shmat第二个参数为NULL(即0)作用是让系统选择一个未使用的地址位置去附上共享内存段
{
perror("shmat");
exit(1);
}
return 1;
}
int Removeshm(int shmid)
{
shmctl(shmid, IPC_RMID, 0);
// printf("Shared memory segment marked for deletion\n");
return 1;
}
int ChangeMode(int shmid, char *mode)
{
struct shmid_ds myshmds;
shmctl(shmid, IPC_STAT, &myshmds);
// printf("Old permissions were: %o\n", myshmds.shm_perm.mode);
//sscanf(mode, "%o", &myshmds.shm_perm.mode);
shmctl(shmid, IPC_SET, &myshmds);
// printf("New permissions are : %o\n", myshmds.shm_perm.mode);
return 1;
}
void Create_Sem(int members) //创建信号量
{
key_t key = 1234;
int i;
union semun sem_opts;
// printf("To create new sem with %d members!\n",members);
fflush(stdout);
if ((sem_id = semget(key,members,IPC_CREAT | IPC_EXCL | 0666)) == -1)
{
fprintf(stderr,"The semaphore is exist!\n");
if((sem_id=semget(key,members,0))==-1)
{
perror("create sem error");
exit(1);
}
//exit(0);
}
sem_opts.val = SEM_MAX;
for (i = 0;i < members;i++)
{
if (semctl(sem_id,i,SETVAL,sem_opts) == -1)
{
fprintf(stderr,"set val error!\n");
exit(0);
}
}
}
int P_Sem(int sem_id,int sem_num) //P操作
{
struct sembuf sem_b;
sem_b.sem_num = sem_num;
sem_b.sem_op = -1;
sem_b.sem_flg = SEM_UNDO;
if (semop(sem_id,&sem_b,1) == -1)
{
return 0;
}
return 1;
}
int V_Sem(int sem_id,int sem_num) //V操作
{
struct sembuf sem_b;
sem_b.sem_num = sem_num;
sem_b.sem_op = 1;
sem_b.sem_flg = SEM_UNDO;
if (semop(sem_id,&sem_b,1) == -1)
{
return 0;
}
return 1;
}
int del_semvalue(int sem_id) //删除信号量
{
union semun sem_union;
if(semctl(sem_id,0,IPC_RMID,sem_union) == -1)
{
printf("\nsem delete fail!\n");
return 0;
}
// printf("\nsem delete!");
fflush(stdout);
return 1;
}
void Up_Total(int num)//服务器上传文件总数
{
P_Sem(sem_id,0);
g_segptr->uptotal+=num;
V_Sem(sem_id,0);
}
void Down_Total(int num)//服务器下载文件总数
{
P_Sem(sem_id,1);
g_segptr->downtotal+=num;
V_Sem(sem_id,1);
}
void Up_Size(int size)//服务器上传文件大小
{
P_Sem(sem_id,2);
g_segptr->upsize += size;
V_Sem(sem_id,2);
}
void Down_Size(int size)//服务器下载文件大小
{
P_Sem(sem_id,3);
g_segptr->downsize += size;
V_Sem(sem_id,3);
}
int Get_Up_Total()//服务器上传文件总数
{
int temp;
P_Sem(sem_id,0);
temp = g_segptr->uptotal;
V_Sem(sem_id,0);
return temp;
}
int Get_Down_Total()//服务器下载文件总数
{
int temp;
P_Sem(sem_id,1);
temp = g_segptr->downtotal;
V_Sem(sem_id,1);
return temp;
}
long Get_Up_Size()//服务器上传文件大小
{
long temp;
P_Sem(sem_id,2);
temp = g_segptr->upsize;
V_Sem(sem_id,2);
return temp;
}
long Get_Down_Size()//服务器下载文件大小
{
long temp;
P_Sem(sem_id,3);
temp = g_segptr->downsize;
V_Sem(sem_id,3);
return temp;
}
void start_timeout(int signal)
{
//printf("子进程发送信号过来\n");
is_have_timeout=1;
}
void stop_timeout(int signal)
{
is_have_timeout=0;
}
void To_Send_Signal_Start_Timeout()
{
pid_t ppid;
ppid=getppid();//取得父进程ID
kill(ppid,SIGUSR1);//发送SIGUSR1信号
}
//读取配制文件 返回0就是读取失败 1就是成功 第一个参数是数据要存的指针,第二个是最多读取信息数 第三个指向是用来返回最终读取了多少条信息
int ReadConfigInfo(struct configInfo * config,int maxReadCount,int *alreadyReadCount)
{
FILE * file=fopen("miniftp.conf","r");
if(file==NULL)
{
printf("File Open Error");
return 0;
}
//struct configInfo config[10];
char buffer[128]={0};
int buffer_size=128;
int read_count=0;
while(fgets(buffer,buffer_size,file)!=NULL)
{
if(buffer[0]!=35 && buffer[0]!='\n') //#的ascii码为35
{
int position=0; //字符保存的位置
char * pBuffer=buffer;
//取出键名
while(!isspace(*pBuffer))
{
*(config[read_count].keyname+position)=*pBuffer;//将字符保存进结构体
position++;
pBuffer++;
}
*(config[read_count].keyname+position)='\0';
//printf("%s\t",&(config[read_count].keyname));
//从键名后查找非空字符的位置
while(isspace(*(++pBuffer)))
{}
position=0;
//将非空字符保存起来,直到回车符为止
while(*pBuffer!='\n')
{
*(config[read_count].value+position)=*pBuffer;
position++;
pBuffer++;
}
*(config[read_count].value+position)='\0';
//printf("%s\n",&(config[read_count].value));
read_count++;
if(read_count>=maxReadCount)
{
break;
}
}
}
/*
int size;
for (size=0;size<read_count; size++)
{
printf("%s\t",config[size].keyname);
printf("%s\n",config[size].value);
}
*/
*alreadyReadCount=read_count;
fclose(file);
//getchar();
return 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -