#include<unistd.h>#include<stdio.h>#include<stdlib.h>#include<string.h>#include<fcntl.h>#include<sys/wait.h>#include<sys/stat.h>#include<sys/types.h>constchar*constusage_msg="usage: ./host [host_id] [random_key] [depth]";constchar*constwrite_fifo_name="Host.FIFO";#define FIFO_NAME_MAX 128constintROOT_HOST_DEP=0;constintCHILD_HOST_DEP=1;constintLEAF_HOST_DEP=2;constintROUND_NUM=10;typedefstruct{intplayer_id,score,rank;}PlayerRecord;typedefstruct{pid_tpid;intwr_pipe_fd,rd_pipe_fd;}Child;voidERR_EXIT(char*msg){perror(msg);exit(128);}voidflush_fsync(FILE*stream){fflush(stream);fsync(fileno(stream));}voidread_player_id(intplayer_id_list[],intn,intfd);intsublist(intlist[],intL,intR,charbuf[]);voidfork_child(Childchild_list[],intplayer_id_list[],intdepth,char*argv[]);voidrun_game(Childchild_list[],intdepth,void*extra);voidcalc_rank(PlayerRecordplayer_record_list[]);voidclean_child(Childchild_host_list[]);intmain(intargc,char*argv[]){if(argc!=4){// the number of arguments should be exactly 3fprintf(stderr,usage_msg);exit(2);}inthost_id=atoi(argv[1]);intrandom_key=atoi(argv[2]);intdepth=atoi(argv[3]);if(depth==ROOT_HOST_DEP){// fifo for read from bidding systemcharfifo_path[FIFO_NAME_MAX];snprintf(fifo_path,FIFO_NAME_MAX,"Host%d.FIFO",host_id);intread_fifo_fd=open(fifo_path,O_RDONLY);if(read_fifo_fd==-1)ERR_EXIT("open");// fifo for write to bidding systemintwrite_fifo_fd=open(write_fifo_name,O_WRONLY);if(write_fifo_fd==-1)ERR_EXIT("open");// fork 2 child hostsChildchild_host_list[2];fork_child(child_host_list,NULL,depth,argv);while(1){intplayer_id_list[8];read_player_id(player_id_list,8,read_fifo_fd);if(player_id_list[0]==-1){for(inti=0;i<2;i++){char*msg="-1 -1 -1 -1\n";write(child_host_list[i].wr_pipe_fd,msg,strlen(msg));fsync(child_host_list[i].wr_pipe_fd);}break;}// assign players to 2 child hostsfor(inti=0;i<2;i++){charbuf[BUFSIZ];intlen=sublist(player_id_list,i*(4>>depth),i*(4>>depth)+(4>>depth),buf);write(child_host_list[i].wr_pipe_fd,buf,len);fsync(child_host_list[i].wr_pipe_fd);}// init player recordPlayerRecordplayer_record_list[8];for(inti=0;i<8;i++){player_record_list[i].player_id=player_id_list[i];player_record_list[i].score=0;}run_game(child_host_list,depth,player_record_list);calc_rank(player_record_list);charbuf[BUFSIZ];char*p=buf;p+=snprintf(buf,BUFSIZ,"%d\n",random_key);for(inti=0;i<8;i++){p+=snprintf(p,BUFSIZ,"%d %d\n",player_record_list[i].player_id,player_record_list[i].rank);}write(write_fifo_fd,buf,strlen(buf));fsync(write_fifo_fd);}clean_child(child_host_list);close(read_fifo_fd);close(write_fifo_fd);}elseif(depth==CHILD_HOST_DEP){Childleaf_host_list[2];fork_child(leaf_host_list,NULL,depth,argv);while(1){intplayer_id_list[4];read_player_id(player_id_list,4,STDIN_FILENO);if(player_id_list[0]==-1){for(inti=0;i<2;i++){char*msg="-1 -1\n";write(leaf_host_list[i].wr_pipe_fd,msg,strlen(msg));fsync(leaf_host_list[i].wr_pipe_fd);}break;}for(inti=0;i<2;i++){charbuf[BUFSIZ];intlen=sublist(player_id_list,i*(4>>depth),i*(4>>depth)+(4>>depth),buf);write(leaf_host_list[i].wr_pipe_fd,buf,len);fsync(leaf_host_list[i].wr_pipe_fd);}run_game(leaf_host_list,depth,NULL);}clean_child(leaf_host_list);}elseif(depth==LEAF_HOST_DEP){while(1){intplayer_id_list[2];read_player_id(player_id_list,2,STDIN_FILENO);if(player_id_list[0]==-1){break;}Childplayer_list[2];fork_child(player_list,player_id_list,depth,argv);run_game(player_list,depth,NULL);clean_child(player_list);}}returnEXIT_SUCCESS;}voidread_player_id(intplayer_id_list[],intn,intfd){charbuf[BUFSIZ];char*p=buf;read(fd,p,BUFSIZ);for(inti=0;i<n;i++){player_id_list[i]=strtol(p,&p,10);}}intsublist(intlist[],intL,intR,charbuf[]){char*ptr=buf;for(inti=L;i<R;i++)ptr+=snprintf(ptr,BUFSIZ,"%d%c",list[i]," \n"[i==R-1]);return(ptr-buf);}voidfork_child(Childchild_list[],intplayer_id_list[],intdepth,char*argv[]){for(inti=0;i<2;i++){// pipeintpfd[2][2];intpip_res1=pipe(pfd[0]);// parent read, child writeintpip_res2=pipe(pfd[1]);// parent write, child readif(pip_res1==-1||pip_res2==-1)ERR_EXIT("pipe");// forkchild_list[i].pid=fork();if(child_list[i].pid==-1){ERR_EXIT("fork");}elseif(child_list[i].pid==0){// childclose(pfd[0][0]);dup2(pfd[0][1],1);close(pfd[0][1]);close(pfd[1][1]);dup2(pfd[1][0],0);close(pfd[1][0]);if(depth!=LEAF_HOST_DEP){charnext_dep[4];snprintf(next_dep,4,"%d",depth+1);execl("./host","host",argv[1],argv[2],next_dep,NULL);}else{charbuf[4];snprintf(buf,4,"%d",player_id_list[i]);execl("./player","player",buf,NULL);}}else{// parentclose(pfd[0][1]);child_list[i].rd_pipe_fd=pfd[0][0];close(pfd[1][0]);child_list[i].wr_pipe_fd=pfd[1][1];}}}voidrun_game(Childchild_list[],intdepth,void*extra){PlayerRecord*player_record_list=(PlayerRecord*)extra;intid_2_idx[32];for(inti=0;depth==0&&i<8;i++)id_2_idx[player_record_list[i].player_id]=i;for(intround=1;round<=ROUND_NUM;round++){// read result from two child hostsintplayer_id[2],money[2];charbuf[BUFSIZ];read(child_list[0].rd_pipe_fd,buf,BUFSIZ);sscanf(buf,"%d %d",&player_id[0],&money[0]);read(child_list[1].rd_pipe_fd,buf,BUFSIZ);sscanf(buf,"%d %d",&player_id[1],&money[1]);// compare two resultsintwinner_id,win_money;if(money[0]>money[1]){winner_id=player_id[0];win_money=money[0];}else{winner_id=player_id[1];win_money=money[1];}if(depth==0){// if dep == 0: update player score and write winner to 2 child++player_record_list[id_2_idx[winner_id]].score;if(round!=ROUND_NUM){for(inti=0;i<2;i++){intlen=sprintf(buf,"%d\n",winner_id);write(child_list[i].wr_pipe_fd,buf,len);fsync(child_list[i].wr_pipe_fd);}}}else{// if dep > 0: write winner, money to stdout and read final winner from stdin and write final winner to 2 childintlen=sprintf(buf,"%d %d\n",winner_id,win_money);write(STDOUT_FILENO,buf,len);fsync(STDOUT_FILENO);if(round!=ROUND_NUM){intlen=read(STDIN_FILENO,buf,BUFSIZ);for(inti=0;i<2;i++){write(child_list[i].wr_pipe_fd,buf,len);fsync(child_list[i].wr_pipe_fd);}}}}}intcmp(constvoid*a,constvoid*b){intx=(*(PlayerRecord**)a)->score,y=(*(PlayerRecord**)b)->score;return(x<y)-(x>y);}voidcalc_rank(PlayerRecordplayer_record_list[]){PlayerRecord*ptr[8];for(inti=0;i<8;i++)ptr[i]=&player_record_list[i];qsort(ptr,8,sizeof(PlayerRecord*),cmp);ptr[0]->rank=1;for(inti=1;i<8;i++)ptr[i]->rank=(ptr[i]->score==ptr[i-1]->score)?ptr[i-1]->rank:i+1;}voidclean_child(Childchild_list[]){for(inti=0;i<2;i++){intstatus;waitpid(child_list[i].pid,&status,0);close(child_list[i].rd_pipe_fd);close(child_list[i].wr_pipe_fd);}}
#include<unistd.h>#include<stdio.h>#include<stdlib.h>constchar*constusage_msg="usage: ./player [player_id]";constintROUND_NUM=10;voidERR_EXIT(char*msg){perror(msg);exit(128);}voidflush_fsync(FILE*stream){fflush(stream);fsync(fileno(stream));}voidread_winner_id(){intwinner_id;scanf("%d",&winner_id);}voidtell_host_money(intplayer_id,intmoney){printf("%d %d\n",player_id,money);flush_fsync(stdout);}intmain(intargc,char*argv[]){if(argc!=2){// the number of arguments should be exactly 1fprintf(stderr,usage_msg);exit(2);}constintplayer_id=atoi(argv[1]);constintmoney=player_id*100;for(intround=1;round<=ROUND_NUM;++round){if(round>1)read_winner_id();tell_host_money(player_id,money);}returnEXIT_SUCCESS;}