#include <signal.h> #include <stdio.h> #ifdef SYSV #include <string.h> #else #include <strings.h> #endif #include <ctype.h> #include <sys/types.h> #include <netinet/in.h> #include <sys/socket.h> #include <sys/time.h> #include "config.h" #include "sys_proto.h" #include "string.h" #include "netio.h" #include "buf.h" #include "netio_private.h" #include "servers.h" static const char *create_fail = "Either there is already a player with that name, or that name is illegal.\r\n"; static const char *connect_fail = "Either that player does not exist, or has a different password.\r\n"; static void check_connect(Player *p, char *msg); static void stop_programming(Player *p); void tell(Playerid player, const char *msg) { Player *p; String *str; for(p = players; p; p = p->next) { if (p->connected && p->id == player) { str = string_cpy(msg); str = string_cat(str, "\r\n"); buf_add(&p->output, str); break; } } } void boot(Playerid who) { Player *p; for(p = players; p; p = p->next) { if (p->connected && p->id == who) { write(p->fd, DISCONNECT_MSG, strlen (DISCONNECT_MSG)); disconnect_player(p->id); remove_player(p); break; } } } void player_command(Player *p, char *command) { if (!p->connected) { check_connect(p, command); } else if (p->isprogramming) { if (!strcmp(command, ".")) { stop_programming(p); } else { fprintf(p->progfile, "%s\n", command); } } else { while(isspace(*command)) { command++; } p->parsing = 1; parse(p->id, command); } } void parse_done(Playerid player) { Player *p; for(p = players; p; p = p->next) { if(p->id == player) { p->parsing = 0; } } } static Player * find_connect(Playerid player, Player *not) { Player *p; for (p = players; p; p = p->next) { if (p != not && p->connected && p->id == player) { return p; } } return 0; } static void check_connect(Player *p, char *msg) { char *command, *user, *password; Playerid player; Player *oldp; parse_connect(msg, &command, &user, &password); if (!strncmp(command, "co", 2)) { player = connect_player(user, password); if (player == NOTHING) { write(p->fd, connect_fail, strlen(connect_fail)); writelog(); fprintf(stderr, "Player failed connect %s on descriptor %d\n", user, p->fd); } else if ((oldp = find_connect(player, p))) { writelog(); fprintf(stderr, "Player %s(#%d) transferred from fd %d to fd %d\n", user, player, oldp->fd, p->fd); p->connected = 1; p->id = player; write(oldp->fd, TRANSFER_MSG1, strlen(TRANSFER_MSG1)); remove_player(oldp); write(p->fd, TRANSFER_MSG2, strlen(TRANSFER_MSG2)); write(p->fd, CONNECT_MSG, strlen(CONNECT_MSG)); } else { writelog(); fprintf(stderr, "Player connected %s(#%d) on descriptor %d\n", user, player, p->fd); p->connected = 1; p->id = player; write(p->fd, CONNECT_MSG, strlen(CONNECT_MSG)); } } else if (!strncmp(command, "cr", 2) && !registration) { player = create_player (user, password); if (player == NOTHING) { write(p->fd, create_fail, strlen(create_fail)); writelog(); fprintf(stderr, "Player failed create %s on descriptor %d\n", user, p->fd); } else { writelog(); fprintf(stderr, "Player created: %s(#%d) on descriptor %d\n", user, player, p->fd); p->connected = 1; p->id = player; write (p->fd, CONNECT_MSG, strlen (CONNECT_MSG)); } } else { write(p->fd, welcome, strlen(welcome)); } } void parse_connect (char *msg, char **command, char **user, char **pass) { while (*msg && isascii(*msg) && isspace (*msg)) /* skip whitespace */ msg++; *command = msg; while (*msg && isascii(*msg) && !isspace (*msg)) /* skip command */ msg++; if (*msg) { *msg++ = '\0'; /* terminate cmd */ } while (*msg && isascii(*msg) && isspace (*msg)) /* skip whitespace */ msg++; *user = msg; while (*msg && isascii(*msg) && !isspace (*msg)) /* skip user */ msg++; if (*msg) { *msg++ = '\0'; /* terminate user */ } while (*msg && isascii(*msg) && isspace (*msg)) /* skip whitespace */ msg++; *pass = msg; while (*msg && isascii(*msg) && !isspace (*msg)) /* skip password */ msg++; *msg = '\0'; /* terminate pass */ } int start_programming(Playerid player, GENPTR *progwhat) { Player *p; for (p = players; p; p = p->next) { if (p->id == player) { break; } } if (!p) { return -1; } sprintf(p->progfilename, "%s/%s_%d", PROGDIR, serv_id2name(0), player); if (!(p->progfile = fopen(p->progfilename, "w"))) { writelog(); fprintf(stderr, "Couldn't open programming temp file "); perror(p->progfilename); p->progfilename[0] = '\0'; return -2; } else { p->isprogramming = 1; p->progwhat = (void *) progwhat; return 0; } } static Playerid progr; /* programmer */ static void stop_programming(Player *p) { fclose(p->progfile); p->isprogramming = 0; if (!(p->progfile = fopen(p->progfilename, "r"))) { writelog(); perror(p->progfilename); } else { progr = p->id; do_compile(p->id, p->progfile, p->progwhat); fclose(p->progfile); unlink(p->progfilename); } tell(p->id, "Exiting programming mode."); p->progfilename[0] = '\0'; p->progfile = 0; } #define MSEC(T) (T.tv_sec * 1000 + T.tv_usec / 1000) struct timeval msec2timeval(int msec) { struct timeval r; r.tv_sec = msec / 1000; r.tv_usec = (msec % 1000 ) * 1000; return r; } void queue_player_commands(struct timeval cur_time, struct timeval *timeout) { Player *p; int msec_since_last; static struct timeval last = {0, 0}; struct timeval new; msec_since_last = MSEC(cur_time) - MSEC(last); last = cur_time; for (p = players; p; p = p->next) { p->quota += msec_since_last; if (p->quota > MAX_CMDS * MSEC_PER_CMD) { p->quota = MAX_CMDS * MSEC_PER_CMD; } if (p->input.head && p->quota >= 0 && !p->parsing) { player_command(p, p->input.head->str->str); buf_delhead(&p->input); if (!p->isprogramming) { p->quota -= MSEC_PER_CMD; } } if (p->input.head && p->quota < 0) { /* return when quota is positive */ new = msec2timeval(-p->quota); *timeout = (timercmp(&new, timeout, <)) ? new : *timeout; } } }