void usa_objecto (int i, pid_t pid) { int u, p; u = find_user_index (pid); p = find_user_playing_index (pid); user_list[u].hp += user_list[u].saco[i].hp_diff; users_playing[p].hp += users_playing[p].saco[i].hp_diff; // garantir que o hp nao fica maior que hp_max if (user_list[u].hp >= user_list[u].hp_max) user_list[u].hp = user_list[u].hp_max; if (users_playing[p].hp >= users_playing[p].hp_max) users_playing[p].hp = users_playing[p].hp_max; // pode-se usar o objecto as vezes que quiser se max_suo==0 if (user_list[u].saco[i].max_uso == 0) return; // case exceda o numero de usos remover do saco user_list[u].saco[i].n_uso++; users_playing[p].saco[i].n_uso++; if (user_list[u].saco[i].n_uso == user_list[u].saco[i].max_uso) remove_object_saco (i, user_list[u].client_pid); if (users_playing[p].saco[i].n_uso == users_playing[p].saco[i].max_uso) remove_object_saco (i, users_playing[p].client_pid); }
/* * Add a new user */ void add_user(user_chat_box_t *users, char *buf, int server_fd) { /***** Insert YOUR code *******/ /* * Check if user limit reached. * * If limit is okay, add user, set up non-blocking pipes and * notify on server shell * * NOTE: You may want to remove any newline characters from the name string * before adding it. This will help in future name-based search. */ int i; pid_t pid; char* user_name = extract_name(ADD_USER, buf); char msg[MSG_SIZE]; char arg1[MSG_SIZE]; char arg2[MSG_SIZE]; if (find_user_index(users, user_name) != -1){ printf("%s already exists.\n", user_name); return; } else { if ((i = find_empty_slot(users)) == -1) { printf("Users are full.\n"); return; } else { sprintf(msg, "Adding %s...\n", user_name); users[i].status = SLOT_FULL; strcpy(users[i].name, user_name); pipe(users[i].ptoc); pipe(users[i].ctop); fcntl(users[i].ptoc[0],F_SETFL, O_NONBLOCK); fcntl(users[i].ctop[0],F_SETFL, O_NONBLOCK); if (write(server_fd, msg, strlen(msg) + 1) < 0) perror("Writing to server shell"); } } //Fork a child process to execute added user's Xterm if ((users[i].pid = fork()) < 0) perror("Add_user fork error"); else if (users[i].pid == 0) { sprintf(arg1, "%d", users[i].ptoc[0]); sprintf(arg2, "%d", users[i].ctop[1]); execl(XTERM_PATH, XTERM, "+hold", "-e", "./shell", arg1, arg2, user_name, (char *)0); } return; }
/* * Send personal message. Print error on the user shell if user not found. */ void send_p2p_msg(int idx, user_chat_box_t *users, char *buf) { /* get the target user by name (hint: call (extract_name() and send message */ char *target_name; int target_idx; char *s; char text[MSG_SIZE]; target_name = extract_name(P2P, buf); target_idx = find_user_index(users, target_name); s = strtok(NULL, SH_DELIMS); //extract the messege sprintf(text, "%s : %s", users[idx].name, s); write(users[target_idx].ptoc[1], text, strlen(text) + 1); }
void apanha_objecto (int i, pid_t pid) { int u, p; user_t c; u = find_user_index (pid); p = find_user_playing_index (pid); c = find_user (pid); // copiar o objecto da sala para o utilizador correspondente // tanto na lista de utilizadores como da dos que estao a jogar user_list[u].saco[user_list[u].n_obj] = labirinto[c.lin][c.col].objectos[i]; user_list[u].peso_saco += labirinto[c.lin][c.col].objectos[i].peso; users_playing[p].saco[users_playing[p].n_obj] = labirinto[c.lin][c.col].objectos[i]; users_playing[p].peso_saco += labirinto[c.lin][c.col].objectos[i].peso; user_list[i].n_obj++; users_playing[i].n_obj++; remove_object_sala (i, c.lin, c.col); }
void remove_object_saco (int i, pid_t pid) { int j, u, p; user_t c; u = find_user_index (pid); p = find_user_playing_index (pid); c = find_user (pid); user_list[u].peso_saco -= user_list[u].saco[i].peso; for (j = i; j < c.n_obj-1; j++) user_list[u].saco[j] = user_list[u].saco[j+1]; memset (&user_list[u].saco[c.n_obj], 0, sizeof (object_t)); users_playing[p].peso_saco -= users_playing[p].saco[i].peso; for (j = i; j < c.n_obj-1; j++) users_playing[p].saco[j] = users_playing[p].saco[j+1]; memset (&users_playing[p].saco[c.n_obj], 0, sizeof (object_t)); user_list[u].n_obj--; users_playing[p].n_obj--; }
int main(int argc, char **argv) { user_chat_box_t user_list[MAX_USERS]; server_ctrl_t server_shell; char arg1[MSG_SIZE]; char arg2[MSG_SIZE]; char command[MSG_SIZE]; int cmd_num; char* str_pid; char* user_name; int k; int i; int idx; /* open non-blocking bi-directional pipes for communication with server shell */ initialize_users(user_list); pipe(server_shell.ptoc); pipe(server_shell.ctop); fcntl(server_shell.ptoc[0],F_SETFL,O_NONBLOCK); fcntl(server_shell.ctop[0],F_SETFL,O_NONBLOCK); /* Fork the server shell */ pid_t pid = fork(); if (pid < 0) printf("Fork error.\n"); else if (pid == 0) { sprintf(arg1, "%d", server_shell.ptoc[0]); sprintf(arg2, "%d", server_shell.ctop[1]); if(execl("./shell", "shell", arg1, arg2, "Server", (char *)0) < 0){ perror("execl error"); } } /* * Inside the child. * Start server's shell. * exec the SHELL program with the required program arguments. */ /* Inside the parent. This will be the most important part of this program. */ /* Start a loop which runs every 1000 usecs. * The loop should read messages from the server shell, parse them using the * parse_command() function and take the appropriate actions. */ else { server_shell.pid = pid; while (1) { /* Let the CPU breathe */ usleep(1000); /* * 1. Read the message from server's shell, if any * 2. Parse the command * 3. Begin switch statement to identify command and take appropriate action * * List of commands to handle here: * CHILD_PID * LIST_USERS * ADD_USER * KICK * EXIT * BROADCAST */ /* Fork a process if a user was added (ADD_USER) */ /* Inside the child */ /* * Start an xterm with shell program running inside it. * execl(XTERM_PATH, XTERM, "+hold", "-e", <path for the SHELL program>, ..<rest of the arguments for the shell program>..); */ if (read(server_shell.ctop[0], command, MSG_SIZE) > 0) { cmd_num = parse_command(command); switch (cmd_num) { case CHILD_PID: str_pid = extract_name(CHILD_PID, command); server_shell.child_pid = atoi(str_pid); break; case LIST_USERS: list_users(user_list, server_shell.ptoc[1]); break; case ADD_USER: add_user(user_list, command, server_shell.ptoc[1]); break; case KICK: user_name = extract_name(KICK, command); if ((idx = find_user_index(user_list, user_name)) == -1) break; cleanup_user(idx, user_list); break; case EXIT: cleanup_users(user_list); cleanup_server(server_shell); break; case BROADCAST: broadcast_msg(user_list, command, server_shell.ptoc[1], "Server"); break; } if(cmd_num == EXIT)break; } /* Back to our main while loop for the "parent" */ /* * Now read messages from the user shells (ie. LOOP) if any, then: * 1. Parse the command * 2. Begin switch statement to identify command and take appropriate action * * List of commands to handle here: * CHILD_PID * LIST_USERS * P2P * EXIT * BROADCAST * * 3. You may use the failure of pipe read command to check if the * user chat windows has been closed. (Remember waitpid with WNOHANG * from recitations?) * Cleanup user if the window is indeed closed. */ int nsize; for (i = 0; i < MAX_USERS; i++) { if (user_list[i].status == SLOT_EMPTY) continue; if ((nsize = read(user_list[i].ctop[0], command, MSG_SIZE)) > 0) { cmd_num = parse_command(command); switch (cmd_num) { case CHILD_PID: str_pid = extract_name(CHILD_PID, command); user_list[i].child_pid = atoi(str_pid); break; case LIST_USERS: list_users(user_list, user_list[i].ptoc[1]); break; case P2P: send_p2p_msg(i, user_list, command); break; case EXIT: cleanup_user(i, user_list); break; case BROADCAST: broadcast_msg(user_list, command, server_shell.ptoc[1], user_list[i].name); break; } } else if(nsize == 0) { int status; if(waitpid(user_list[i].child_pid, &status, WNOHANG) < 0) { cleanup_user(i, user_list); } } } } } /* while loop ends when server shell sees the \exit command */ return 0; }