/* -*- Mode: C -*- */ #include "mcp_shared.cc" static bool fork_player(char *executable, struct player *the_player) { enum { READ = 0, WRITE = 1}; int pipe_out[2]; int pipe_in[2]; if (pipe(pipe_out) != 0) return false; if (pipe(pipe_in) != 0) return false; if ((the_player->pid = fork()) == -1) abort(); if (the_player->pid == 0) { /* Child */ close(pipe_out[READ]); close(pipe_in [WRITE]); dup2(pipe_in [READ], CHILD_IN_FD); dup2(pipe_out[WRITE], CHILD_OUT_FD); setrlimit(RLIMIT_CPU, &cpu_limit); setrlimit(RLIMIT_AS, &mem_limit); execl(executable, executable, 0); perror("execl"); _exit(EXEC_FAILED); } else { /* Parent */ /* Stop the player until it is his turn. */ if (kill(the_player->pid, SIGSTOP) < 0) return false; /* Close useless ends of pipes */ close(pipe_out[WRITE]); close(pipe_in [READ]); the_player->pipe_from_player = pipe_out[READ]; the_player->pipe_to_player = pipe_in[WRITE]; } return true; } int main(int argc, char **argv) { char const *init_state = "O...........................OX......XO..........................."; fprintf(stderr, "Master Control Program\n"); int opt; while ((opt = getopt(argc, argv, "dT:t:m:M:s:")) != -1) { switch (opt) { case 'd': debug = true; break; case 't': cpu_limit.rlim_cur = strtoul(optarg, NULL, 0); break; case 'T': cpu_limit.rlim_max = strtoul(optarg, NULL, 0); break; case 'm': mem_limit.rlim_cur = strtoul(optarg, NULL, 0) << 20; break; case 'M': mem_limit.rlim_max = strtoul(optarg, NULL, 0) << 20; break; case 's': init_state = optarg; break; case ':': case '?': goto usage; } } if (optind + 2 > argc) { usage: print_usage(); exit(1); } setup_signal_handlers(); if (!fork_player(argv[optind], &player[0]) || !fork_player(argv[optind + 1], &player[1])) exit_msg(EXEC_FAILED, "Unable to fork players.\n"); game_state state; initialize_state(&state, init_state); idx_t player_no = state.player() == PLAYER_1 ? 0 : 1; while (!is_final_state(&state)) { game_move move; state.player(static_cast(player_no)); char timeBuf[64]; getTimeStr(timeBuf, 64); printf("[%s] P%u's turn.\nState:\n", timeBuf, player_no); fflush(stdout); state.dump_to_stdio(); //serialize_state(STDOUT_FILENO, &state); printf("\n"); if (!player_move(&player[player_no], &state, &move)) { if (debug) { printf("No move from player %d.\n", player_no); continue; } exit_msg(exit_reason(CRASH_0 + player_no), "No move from player %u.\n", player_no); } if (!apply_move(&state, &move)) { printf("Invalid move from player %u.\n", player_no); exit_msg(exit_reason(INVALID_MOVE_0 + player_no), "Invalid move from player %u.\n", player_no); } printf("P%u moves.\n", player_no); player_no = 1 - player_no; } printf("\nFinal state:\n"); fflush(stdout); serialize_state(STDOUT_FILENO, &state); fprintf(stderr, "\n\nEnd of Line.\n"); printf("\nFinal result: %d : %d\n", state.count_of_type(PLAYER_1), state.count_of_type(PLAYER_2)); /* Kill players */ for (int i = 0; i < 2; i++) { int status; kill(player[i].pid, SIGTERM); kill(player[i].pid, SIGCONT); waitpid(player[i].pid, &status, 0); } return 0; }