功能需求:
利用定时器、进程间信号通信等知识,实现对整个考试过程的控制。考生通过ssh远程登录到考试服务器,
(1)若首次登录则从特定目录复制试卷到用户主目录并命名为用户的登录名,然后记录考生的登录信息并显示考试注意事项,登录信息包括:用户名、登录IP、时间、考试是否已经结束。设置定时器:15分钟提示、5分钟提示(通过write)、时间用完后结束考试(结束用户登录);
(2)若非首次登录,首先检查是否和首次登录的IP是否一致。若不一致关闭登录;若一致再检查考试是否结束,若已经结束,关闭登录,若考试尚未结束重新设置定时器。
(3)要求为考生显示出考试的注意事项,例如考生通过输入 notice 命令即可显示考试的注意事项。该系统还应该具有 submit 功能,即提交试卷,且试卷提交之后就不允许在同一 IP 再登录了。
由于实习时间限制,该程序号存在一个重要问题,即不能置于后台运行。
主体思路还是用字典树维护用户信息,hash绑定用户名和IP。利用管道完成父子进程的通信(所有信息需放在一个字符串中,否则会阻塞)。利用当地时间转换成到1970年的秒数控制时间。利用守护进程使得程序在 后台运行。将目录放在/bin/下,是考生进入系统后自动运行(这一步没有完成)。
#include <stdio.h>
#include <stdlib.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<string.h>
#include<unistd.h>
#include<time.h>
#include<fcntl.h>
#include<signal.h>
#define N 1005
#define M 20000005
#define min 60
//#define int long long
#define ll int
int pipe_fd[2];
char buf_r[N],buf_w[N];
pid_t re;
int fin;
ll f[M];
int Tire[N][30],Tot=1;
int End[M],Use[M];
int tag=60;
int flag;
int ti=24;
void Insert(char s[])
{
int sz=strlen(s);
int p=1,i;
for(i=0;i<sz;i++)
{
int ch=s[i]-'a';
if(!Tire[p][ch]) Tire[p][ch]=++Tot;
p=Tire[p][ch];
}
End[p]=1;
}
int Serch(char s[])
{
int sz=strlen(s);
int p=1,i;
for(i=0;i<sz;i++)
{
p=Tire[p][s[i]-'a'];
if(!p) return 0;
}
if(!End[p]) return 0;
Use[p]++;
if(Use[p]==1) return 1;
return 2;
}
int tire[N][30],tot=1;
int end[M],use[M];
void insert(char s[])
{
int sz=strlen(s);
int p=1,i;
for(i=0;i<sz;i++)
{
int ch=s[i]-'a';
if(!tire[p][ch]) tire[p][ch]=++tot;
p=tire[p][ch];
}
end[p]=1;
}
int serch(char s[])
{
int sz=strlen(s);
int p=1,i;
for(i=0;i<sz;i++)
{
p=tire[p][s[i]-'a'];
if(!p) return 0;
}
if(!end[p]) return 0;
use[p]++;
if(use[p]==1) return 1;
return 2;
}
int gettime()
{
time_t timep;
struct tm *p;
time_t now;
time(&timep);
p=localtime(&timep);
now=mktime(p);
return now;
}
int checktime()
{
if(flag==0)
{
if(gettime()+15*min>=fin)
{
flag=1;
return 1;
}
}
if(flag==1)
{
if(gettime()+5*min>=fin)
{
flag=2;
return 2;
}
}
return 0;
}
void openpipe()
{
memset(buf_r,0,sizeof(buf_r));
memset(buf_w,0,sizeof(buf_w));
if((pipe(pipe_fd))<0)
{
printf("Pipeline creation failed\n");
exit(-1);
}
}
void connection()
{
printf("To connect, please enter: ssh s20190xxxxx@120.95.132.8 -p 6022, please make sure to wrap after input\n");
char s[N],s1[N],s2[N],s3[N];
memset(s,0,sizeof(s));
memset(s1,0,sizeof(s1));
memset(s2,0,sizeof(s2));
memset(s3,0,sizeof(s3));
scanf("%s%s%s%s",s,s1,s2,s3);
strcat(s," ");
strcat(s,s1);
strcat(s," ");
strcat(s,s2);
strcat(s," ");
strcat(s,s3);
system(s);
}
ll getip(char s[])
{
int i;
ll sum=0;
int len=strlen(s);
for(i=0;i<len;i++) sum=sum*1331+s[i];
return sum;
}
int getyonghu(char s[])
{
int ret=0,i;
int len=strlen(s);
for(i=5;i<len;i++) ret=ret*10+s[i]-'0';
return ret;
}
void back()
{
ti--;
tag=(fin-gettime())/min;
fin=gettime()+60*min*24;
}
void login()
{
connection();
// printf("xxxx\n");
openpipe();
re=fork();
if(re<0)
{
printf("Failed to create child process\n");
exit(-1);
}
if(re==0)
{
close(pipe_fd[1]);
char s[N],s1[N],ss[N],s3[N];
int lenss;
memset(s,0,sizeof(s));
memset(s1,0,sizeof(s1));
memset(s3,0,sizeof(s3));
memset(ss,0,sizeof(ss));
printf("Please input again: user name, IP\n");
scanf("%s%s",s,s1);
strcpy(s3,s);
if(Serch(s)!=0)
{
strcat(s,"?");
strcat(s,s1);
if((write(pipe_fd[0],s,strlen(s)))>0) {}
printf("You have handed in your paper\n");
close(pipe_fd[0]);
// close(pipe_fd[0]);
exit(0);
}
strcat(s,"?");
strcat(s,s1);
if(serch(s3)==0) printf("This is your first login\n");
if((write(pipe_fd[0],s,strlen(s)))>0) {}
if(f[getyonghu(s3)]=getip(s1)&&f[getyonghu(s3)]!=-1)
{
printf("User name does not match IP\n");
back();
close(pipe_fd[0]);
exit(0);
}
// printf("xxxxxxx\n");
// if((write(pipe_fd[0],s1,strlen(s1)))>0) {}
// if((lenss=read(pipe_fd[0],ss,N))<0) {}
// printf("%s\n",ss);
// if(strcmp(ss,"Login failed")==0)
// {
// back();
// close(pipe_fd[0]);
// exit(0);
// }
while(gettime()<=fin)
{
char s2[N];
memset(s2,0,sizeof(s2));
int len2;
int nowtime=checktime();
if(nowtime==1) strcat(s2,"The test time is less than 15 minutes. Please take the time\n");
if(nowtime==2) strcat(s2,"The test time is less than 5 minutes. Please take the time\n");
printf("%s",s2);
getchar();
// if((len2=read(pipe_fd[0],s2,N))>0) printf("%s\n",s2);
// sleep(min*2*1000);
printf("If there are other operations, please enter 1, otherwise enter others\n");
printf("If you want to see the exam notes, enter 2\n");
char op[N];
scanf("%s",op);
if(op[0]=='1') break;
else if(op[0]=='2')
{
printf("Please do not log in to other websites, please pay attention to the time\n");
}
}
back();
close(pipe_fd[0]);
exit(0);
}
else
{
close(pipe_fd[0]);
// sleep(min*1000);
int len=0,i,len1=0,len3;
char s[N],s1[N],ss[N],s3[N];
memset(s,0,sizeof(s));
memset(s1,0,sizeof(s1));
memset(s3,0,sizeof(s3));
memset(ss,0,sizeof(ss));
int chose=0;
if((len=read(pipe_fd[1],s3,N))<0) printf("The system could not read in the user name, login failed\n"),chose=1;
len3=strlen(s3);
for(i=0;s3[i]!='?',i<len3;i++) s[len++]=s3[i];
s[len]='\0';
for(;i<len3;i++) if(s3[i]!='?') s1[len1++]=s3[i];
s1[len1]='\0';
// if((len1=read(pipe_fd[1],s1,N))<0) printf("The system can't read IP, login failed\n"),chose=1;
if(Serch(s)!=0)
{
// printf("The examinee has handed in the paper and cannot log in\n");
chose=1;
}
if(serch(s)==0)
{
// printf("The examinee logs in for the first time and issues the test paper\n");
insert(s);
// system("cp C:\Users\DELL\Desktop\WEB3\第三次实习(11,13,14周)\第三次实习(11,13,14周) /home");
f[getyonghu(s)]=getip(s1);
}
else
{
// printf("Candidates have already logged in\n");
if(f[getyonghu(s)]!=getip(s1))
{
// printf("The IP is inconsistent with the IP entered for the first time. Login failed");
chose=1;
// waitpid(re,NULL,0);
// return;
}
}
if(gettime()>=fin)
{
// printf("The test is over, candidates can't log in\n");
chose=1;
}
// if(chose==1) strcat(ss,"Login failed");
// else strcat(ss,"Login successful");
// if((write(pipe_fd[0],ss,strlen(ss)))>0) {}
if(chose==1)
{
waitpid(re,NULL,0);
close(pipe_fd[0]);
return;
}
long res;
int exitcode=0;
// res=wait(&exitcode);
// while(res!=-1)
// {
// char s2[N];
// memset(s2,0,sizeof(s2));
// int nowtime=checktime();
// if(nowtime==1) strcat(s2,"The test time is less than 15 minutes. Please take the time");
// if(nowtime==2) strcat(s2,"The test time is less than 5 minutes. Please take the time");
// if((write(pipe_fd[1],s2,strlen(s2)))<0) printf("Message transfer failed\n");
// sleep(min*1000*2);
// res=wait(&exitcode);
// }
back();
waitpid(re,NULL,0);
close(pipe_fd[0]);
return;
}
}
void settime()
{
fin=gettime()+tag*min;
}
void submit()
{
char s[N];
getchar();
printf("please input user name\n");
scanf("%s",s);
Insert(s);
printf("submint sucessfully\n");
}
void quit()
{
system("logout");
printf("sucessfully\n");
}
void daemonize()
{
pid_t pid;
if((pid=fork())<0) exit(-1);
if(pid!=0) exit(0);
setsid();
if(chdir("/")<0) exit(1);
close(0);
open("/dev/null",O_RDWR);
dup2(0,1);
dup2(0,2);
}
signed main()
{
// daemonize();
memset(f,-1,sizeof(f));
fin=gettime()+60*min*ti;
while(1)
{
if(gettime()>=fin) break;
char op[55];
printf("1.login\n");
printf("2.logout\n");
printf("3.submit\n");
printf("4.Close the exam\n");
scanf("%s",op);
if(op[0]=='1')
{
settime();
login();
}
else if(op[0]=='2')
{
quit();
}
else if(op[0]=='3')
{
// settime();
submit();
}
else if(op[0]=='4') break;
}
printf("The test is over\n");
return 0;
}