Ai
3 Star 9 Fork 1

Doubelmine/C sources files judge system for linux

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
projectGcc.c 12.85 KB
一键复制 编辑 原始数据 按行查看 历史
Doubelmine 提交于 2015-01-04 22:24 +08:00 . 提交项目
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <dirent.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <linux/limits.h>
#include <signal.h>
int runbin;//执行子进程id
int loopflag;//死循环标志位 0为无死循环
int judgeDir(char *argv);//判断是否为目录 为目录返回1 否则程序退出
int openfileRD(char *filename);//只读方式打开某一文件,返回其文件描述符
void adddirargv(char *beforepath,char *afterpath);//对目录进行添加/操作
void createonDir(char *path,char *dirname,char *returndir);//在给定的目录下创建目录 returndir带有/
void writeSome(char *filename,char * buf);//写文件函数
void gccProcess(char *plugdir,char *delwithfilename,char *gccfilename,char *gccofilename);//gcc进程
void runProcess(char *plugdir,char *runfilepath,char **exec);//run进程
void passcorrect(char *iniDir,char *filename);//答案正确
void passfail(char *iniDir,char *filename);//答案错误
void delwithloop(char *iniDir,char *filename);//死循环处理函数
void gccfail(char *iniDir,char *filename);//编译失败处理函数
void initsetini(char **mainargv,/*char *swrunargv int *fd,*/char *rresult,char *swrunargvpath);
void stopLoop(int sig);//死循环处理函数
void extractArgv(char *p,char **execargv);//提取[]分割的参数 p为原始数据,exeargv为提取后保存的数据
void writeResult(char *filename,char *writesome );//写内容 追加方式
void showinf(char *dir,char *file1,char *file2);
void cpfailf(char *cprdir,char *cpddir,char *filename);
void rmcachedir(char * dir);
void main(int argc, char *argv[])
{
if(argc!=2)
{
printf("用法:Bin <要判断的文件目录>\n");
exit(-1);
}
int isDir;
isDir=judgeDir(argv[1]);
if(isDir==1)
{
DIR *dp;
struct dirent *entp;
if((dp=opendir(argv[1]))==NULL)
{
perror("目录打开失败!");
exit(-1);
}
char DirPath[2048]={'\0'};
adddirargv(argv[1],DirPath);
char ComplieDirPath[2048]={'\0'};
char iniDirPath[2048]={'\0'};
char errorf[2048]={'\0'};
//创建编译二进制文件临时存放目录
createonDir(DirPath,"BinCache",ComplieDirPath);
//创建配置文件保存目录
createonDir(DirPath,"Plug",iniDirPath);
createonDir(iniDirPath,"fail",errorf);
//定义需求参数
char correctResult[1024]={'\0'};//正确的结果
char *execvpargv[1024]={'\0'};//执行主函数有参数的变量
initsetini(execvpargv,correctResult,iniDirPath);
int i;
//循环判断目录中的.c文件
while((entp=readdir(dp))!=NULL)
{
if(strstr(entp->d_name,".c")==NULL)//忽略非.c文件
{
continue;
}
//重命名gcc编译后的二进制文件
char complieOfname[1024]={'\0'};
strncat(complieOfname,entp->d_name,strlen(entp->d_name)-2);
//对gcc编译后的二进制文件增加全路径
char allcomplieOfnamePath[2048]={'\0'};
strncat(allcomplieOfnamePath,ComplieDirPath,strlen(ComplieDirPath));
strncat(allcomplieOfnamePath,complieOfname,strlen(complieOfname));
//取得带全路径的文件名
char allPathFileName[2048]={'\0'};
strncpy(allPathFileName,DirPath,strlen(DirPath));
strncat(allPathFileName,entp->d_name,strlen(entp->d_name));
//显示当前处理的进度
printf("--->当前处理的文件为:%s\r",entp->d_name);
fflush(stdout);
//fork子进程进行gcc编译操作
int compliePid;
compliePid=fork();
if(compliePid==0)//gcc编译进程
{
gccProcess(iniDirPath,entp->d_name,allPathFileName,allcomplieOfnamePath);
}
//wait操作
int complieStatus;
wait(&complieStatus);
//判断编译是否通过
if(WEXITSTATUS(complieStatus)>0)//编译没通过
{
gccfail(iniDirPath,entp->d_name);
cpfailf(DirPath,errorf,entp->d_name);
continue;
}
else if(WEXITSTATUS(complieStatus)==0)//编译通过
{
//创建管道用于接收程序的运行结果
int resultfd[2];
if(pipe(resultfd)<0)
{
perror("创建管道用于接收程序的运行结果失败!");
}
//fork子进程用于执行编译好的程序
runbin=fork();
if(runbin==0)//子进程用于运行
{
close(resultfd[0]);
dup2(resultfd[1],1);
int infd;
char temp[2048]={'\0'};
strncpy(temp,iniDirPath,strlen(iniDirPath));
strncat(temp,".runsw.ini",strlen(".runsw.ini"));
infd=open(temp,O_RDONLY);
dup2(infd,0);
runProcess(iniDirPath,allcomplieOfnamePath,execvpargv);
}
alarm(7);
signal(SIGALRM,stopLoop);
//父进程的wait操作
wait(NULL);
if(loopflag==1)//死循环处理
{
delwithloop(iniDirPath,entp->d_name);
cpfailf(DirPath,errorf,entp->d_name);
}
else if(loopflag==0)//非死循环
{
//获取子进程输出数据
close(resultfd[1]);
char runbinresult[PIPE_BUF]={'\0'};
int tempi=0;
do
{
if((tempi=read(resultfd[0],runbinresult,PIPE_BUF))==-1)
break;
}while(tempi>0);
if(memcmp(runbinresult,correctResult,strlen(correctResult))==0)//结果匹配
{
//printf("=|=%s\n",runbinresult );
passcorrect(iniDirPath,entp->d_name);
}
else if(memcmp(runbinresult,correctResult,strlen(correctResult))!=0)//结果不匹配
{
// int fd;
// fd=open("/home/wanghao/eeee/t.log",O_RDWR|O_CREAT|O_APPEND,0666);
// write();
//printf("==%s\n",runbinresult );
passfail(iniDirPath,entp->d_name);
cpfailf(DirPath,errorf,entp->d_name);
}
}
}
}
rmcachedir(ComplieDirPath);//删除缓存目录
printf("\n");
showinf(iniDirPath,"result.log","compileError.log");//显示结果
}
}//<-main函数
int judgeDir(char *argv)//判断是否为目录
{
struct stat dirbuf;//stat结构体用于判断目录
if(stat(argv,&dirbuf)!=0)
{
printf("该参数不是一个目录或者文件:(\n");
exit(0);
}
if(S_ISDIR(dirbuf.st_mode))//目录
{
return 1;
}
else if(S_ISREG(dirbuf.st_mode))
{
if(strstr(argv,".c")==NULL)
{
printf("当前程序版本只能评测C源文件:)\n");
exit(0);
}
else
{
printf("单个C源文件请手动编译,谢谢合作:)\n");
exit(0);
}
}
}
void stopLoop(int sig)
{
if(sig==SIGALRM)
{
loopflag=1;
kill(runbin,SIGTERM);//杀死死循环进程
}
}
void extractArgv(char *p,char **execargv)//处理函数
{
int loopnum=0;
while(*p=='[')
{
execargv[loopnum++]=++p;
while(*p++!=']');
*(p-1)='\0';
}
}
void initsetini(char **mainargv,char *rresult,char *swrunargvpath)
{
printf("请输入程序运行的main函数参数,以[]分割;若为空请直接回车:\n");
char tempmainargv[512]={'\0'};
fgets(tempmainargv,512,stdin);
if(strlen(tempmainargv)==1||strlen(tempmainargv)==0)//空参数
{
}
else
{
tempmainargv[strlen(tempmainargv)-1]='\0';//去掉回车
char tempmainargvCache[820]={'\0'};
strncat(tempmainargvCache,"[temp]",strlen("[temp]"));
strncat(tempmainargvCache,tempmainargv,strlen(tempmainargv));
extractArgv(tempmainargvCache,mainargv);
}
printf("请输入程序运行时需要输入的参数;若为空请直接回车:\n");
char swrunargv[512]={'\0'};
fgets(swrunargv,512,stdin);
if(strlen(swrunargv)==1||strlen(swrunargv)==0)//空参数
{
}
else
{
swrunargv[strlen(swrunargv)-1]='\0';
char temp[2048]={'\0'};
strncpy(temp,swrunargvpath,strlen(swrunargvpath));
strncat(temp,".runsw.ini",strlen(".runsw.ini"));
writeSome(temp,swrunargv);
}
printf("请输入正确的程序运行结果:\n" );
fgets(rresult,512,stdin);
if(strlen(rresult)==0||strlen(rresult)==1)//结果为空
{
}
else
{
rresult[strlen(rresult)-1]='\0';
}
}
void gccProcess(char *plugdir,char *delwithfilename,char *gccfilename,char *gccofilename)//gcc进程 配置文件目录,当前处理的文件名 gcc第一个参数 gcc第二个参数
{
char templugdir[2048]={'\0'};
strncpy(templugdir,plugdir,strlen(plugdir));
int errorlogfd;
strncat(templugdir,"compileError.log",strlen("compileError.log"));
if((errorlogfd=open(templugdir,O_RDWR|O_CREAT|O_APPEND,0666))==-1)
{
perror("函数gccProcess--创建compileError.log错误");
}
char temperror[512]={'\0'};
strncpy(temperror,"\n\n【",strlen("\n\n【"));
strncat(temperror,delwithfilename,strlen(delwithfilename));
strncat(temperror,"】 报错信息(若为空则无错):\n",strlen("】 报错信息(若为空则无错):\n"));
if((write(errorlogfd,temperror,strlen(temperror)))==-1)
{
perror("函数gccProcess--写入数据时出错!\n");
}
dup2(errorlogfd,2);
execlp("gcc","gcc",gccfilename,"-o",gccofilename,NULL);
}
void gccfail(char *iniDir,char *filename)//编译未通过
{
char tempopen[2048]={'\0'};
strncpy(tempopen,iniDir,strlen(iniDir));
strncat(tempopen,"result.log",strlen("result.log"));
char tempin[2048]={'\0'};
strncpy(tempin,"【",strlen("【"));
strncat(tempin,filename,strlen(filename));
strncat(tempin,"】----------语法错误----------编译失败----------得分为0\n",strlen("】----------语法错误----------编译失败----------得分为0\n"));
writeResult(tempopen,tempin);
}
void delwithloop(char *iniDir,char *filename)
{
char tempopen[2048]={'\0'};
strncpy(tempopen,iniDir,strlen(iniDir));
strncat(tempopen,"result.log",strlen("result.log"));
char tempin[2048]={'\0'};
strncpy(tempin,"【",strlen("【"));
strncat(tempin,filename,strlen(filename));
strncat(tempin,"】==========语法正确----------无限循环----------得分为0\n",strlen("】==========语法正确----------无限循环----------得分为0\n"));
writeResult(tempopen,tempin);
loopflag=0;
}
void passfail(char *iniDir,char *filename)//答案不一
{
char tempopen[2048]={'\0'};
strncpy(tempopen,iniDir,strlen(iniDir));
strncat(tempopen,"result.log",strlen("result.log"));
char tempin[2048]={'\0'};
strncpy(tempin,"【",strlen("【"));
strncat(tempin,filename,strlen(filename));
strncat(tempin,"】==========语法正确----------结果错误----------得分为0\n",strlen("】==========语法正确----------结果错误----------得分为0\n"));
writeResult(tempopen,tempin);
}
void passcorrect(char *iniDir,char *filename)//答案统一
{
char tempopen[2048]={'\0'};
strncpy(tempopen,iniDir,strlen(iniDir));
strncat(tempopen,"result.log",strlen("result.log"));
char tempin[2048]={'\0'};
strncpy(tempin,"【",strlen("【"));
strncat(tempin,filename,strlen(filename));
strncat(tempin,"】==========语法正确==========结果正确==========得分为100\n",strlen("】==========语法正确==========结果正确==========得分为100\n"));
writeResult(tempopen,tempin);
}
void writeSome(char *filename,char * buf)//写文件函数
{
int fd;
if((fd=open(filename,O_RDWR|O_CREAT|O_TRUNC,0666))==-1)
{
perror("函数writeSome--文件打开失败!\n");
}
if((write(fd,buf,strlen(buf)))==-1)
{
perror("函数writeSome--写入数据时出错!\n");
}
if((close(fd))==-1)
{
perror("函数writeSome--文件关闭失败!\n");
}
//return fd;
}
int openfileRD(char *filename)//只读方式打开某一文件,返回其文件描述符
{
int fd;
if((fd=open(filename,O_RDONLY))==-1)
{
perror("函数openfileRD--文件打开失败!");
return -1;
}
return fd;
}
void createonDir(char *path,char *dirname,char *returndir)//在给定的目录下创建目录 returndir带有/
{
char temp[2048]={'\0'};
strncpy(temp,path,strlen(path));
strncat(temp,dirname,strlen(dirname));
if(opendir(temp)==NULL)
{
mkdir(temp,0777);
}
adddirargv(temp,returndir);
}
void adddirargv(char *beforepath,char *afterpath)//对目录进行添加/操作
{
if(beforepath[strlen(beforepath)-1]!='/')
{
strncat(beforepath,"/",strlen("/"));
}
strncpy(afterpath,beforepath,strlen(beforepath));
}
void runProcess(char *plugdir,char *runfilepath,char **exec)
{
loopflag=0;
exec[0]=runfilepath;
execvp(runfilepath,exec);
}
void writeResult(char *filename,char *writesome )//写内容
{
int fd;
if((fd=open(filename,O_RDWR|O_CREAT|O_APPEND,0666))==-1)
{
perror("函数writeResult--文件打开失败!");
}
if((write(fd,writesome,strlen(writesome)))==-1)
{
perror("函数writeResult--文件写入失败!");
}
if((close(fd))==-1)
{
perror("函数writeResult--文件关闭失败!");
}
}
void showinf(char *dir,char *file1,char *file2)
{
char temp1[2048]={'\0'};
char temp2[2048]={'\0'};
strncpy(temp1,dir,strlen(dir));
strncpy(temp2,dir,strlen(dir));
strncat(temp1,file1,strlen(file1));
strncat(temp2,file2,strlen(file2));
char *showexe[2048]={'\0'};
showexe[0]="gedit";
showexe[1]=temp1;
showexe[2]=temp2;
int sow;
sow=fork();
if(sow==0)
{
close(2);//关闭标准错误输出
execvp("gedit",showexe);
}
wait(NULL);
}
void cpfailf(char *cprdir,char *cpddir,char *filename)
{
int cpid;
cpid=fork();
if(cpid==0)
{
char temp[2048]={'\0'};
strncpy(temp,cprdir,strlen(cprdir));
strncat(temp,filename,strlen(filename));
execlp("cp","cp",temp,cpddir,NULL);
}
wait(NULL);
}
void rmcachedir(char * dir)
{
int cpid;
cpid=fork();
if(cpid==0)
{
execlp("rm","rm","-r",dir,NULL);
}
wait(NULL);
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C
1
https://gitee.com/doublemine/C-sources-files-judge-system-for-linux.git
git@gitee.com:doublemine/C-sources-files-judge-system-for-linux.git
doublemine
C-sources-files-judge-system-for-linux
C sources files judge system for linux
master

搜索帮助