diff --git a/prompt.c b/prompt.c index eaa8d7b..e4eb259 100644 --- a/prompt.c +++ b/prompt.c @@ -16,10 +16,44 @@ uint8_t pending_requests[MAX_STR_SIZE][CLIENT_ID_SIZE]; // XXX uint8_t num_requests=0; // XXX extern void on_friendadded(int friendnumber); -static void print_usage(ToxWindow *self); static char prompt_buf[MAX_STR_SIZE] = {0}; static int prompt_buf_pos = 0; +/* commands */ +void cmd_accept(ToxWindow *, char **); +void cmd_add(ToxWindow *, char **); +void cmd_clear(ToxWindow *, char **); +void cmd_connect(ToxWindow *, char **); +void cmd_help(ToxWindow *, char **); +void cmd_msg(ToxWindow *, char **); +void cmd_myid(ToxWindow *, char **); +void cmd_nick(ToxWindow *, char **); +void cmd_quit(ToxWindow *, char **); +void cmd_status(ToxWindow *, char **); +void cmd_statusmsg(ToxWindow *, char **); + +#define NUM_COMMANDS 13 + +static struct { + char *name; + int numargs; + void (*func)(ToxWindow *, char **); +} commands[] = { + { "accept", 1, cmd_accept }, + { "add", 2, cmd_add }, + { "clear", 0, cmd_clear }, + { "connect", 3, cmd_connect }, + { "exit", 0, cmd_quit }, + { "help", 0, cmd_help }, + { "msg", 2, cmd_msg }, + { "myid", 0, cmd_myid }, + { "nick", 1, cmd_nick }, + { "q", 0, cmd_quit }, + { "quit", 0, cmd_quit }, + { "status", 2, cmd_status }, + { "statusmsg", 1, cmd_statusmsg }, +}; + // XXX: int add_req(uint8_t *public_key) { @@ -40,6 +74,209 @@ unsigned char *hex_string_to_bin(char hex_string[]) return val; } +void cmd_accept(ToxWindow *self, char **args) +{ + int num = atoi(args[1]); + if (num >= num_requests) { + wprintw(self->window, "Invalid syntax.\n"); + return; + } + + num = m_addfriend_norequest(pending_requests[num]); + if (num == -1) + wprintw(self->window, "Failed to add friend.\n"); + else { + wprintw(self->window, "Friend accepted as: %d.\n", num); + on_friendadded(num); + } +} + +void cmd_add(ToxWindow *self, char **args) +{ + uint8_t id_bin[KEY_SIZE_BYTES]; + char xx[3]; + uint32_t x; + char *id = args[1]; + char *msg = args[2]; + + if (!id) { + wprintw(self->window, "Invalid command: add expected at least one argument.\n"); + return; + } + if (!msg) + msg = ""; + + if (strlen(id) != 2*KEY_SIZE_BYTES) { + wprintw(self->window, "Invalid ID length.\n"); + return; + } + int i; + for (i = 0; i < KEY_SIZE_BYTES; ++i) { + xx[0] = id[2*i]; + xx[1] = id[2*i+1]; + xx[2] = '\0'; + if (sscanf(xx, "%02x", &x) != 1) { + wprintw(self->window, "Invalid ID.\n"); + return; + } + id_bin[i] = x; + } + int num = m_addfriend(id_bin, (uint8_t*) msg, strlen(msg)+1); + switch (num) { + case FAERR_TOOLONG: + wprintw(self->window, "Message is too long.\n"); + break; + case FAERR_NOMESSAGE: + wprintw(self->window, "Please add a message to your request.\n"); + break; + case FAERR_OWNKEY: + wprintw(self->window, "That appears to be your own ID.\n"); + break; + case FAERR_ALREADYSENT: + wprintw(self->window, "Friend request already sent.\n"); + break; + case FAERR_UNKNOWN: + wprintw(self->window, "Undefined error when adding friend.\n"); + break; + default: + wprintw(self->window, "Friend added as %d.\n", num); + on_friendadded(num); + break; + } +} + +void cmd_clear(ToxWindow *self, char **args) +{ + wclear(self->window); +} + +void cmd_connect(ToxWindow *self, char **args) +{ + IP_Port dht; + char *ip = args[1]; + char *port = args[2]; + char *key = args[3]; + + if (atoi(port) == 0) { + wprintw(self->window, "Invalid syntax.\n"); + return; + } + + dht.port = htons(atoi(port)); + uint32_t resolved_address = resolve_addr(ip); + if (resolved_address == 0) { + return; + } + + dht.ip.i = resolved_address; + unsigned char *binary_string = hex_string_to_bin(key); + DHT_bootstrap(dht, binary_string); + free(binary_string); +} + +void cmd_quit(ToxWindow *self, char **args) +{ + endwin(); + exit(0); +} + +void cmd_help(ToxWindow *self, char **args) +{ + wclear(self->window); + wattron(self->window, COLOR_PAIR(2) | A_BOLD); + wprintw(self->window, "Commands:\n"); + wattroff(self->window, A_BOLD); + + wprintw(self->window, " connect : Connect to DHT server\n"); + wprintw(self->window, " add : Add friend\n"); + wprintw(self->window, " status : Set your status\n"); + wprintw(self->window, " statusmsg : Set your status\n"); + wprintw(self->window, " nick : Set your nickname\n"); + wprintw(self->window, " accept : Accept friend request\n"); + wprintw(self->window, " myid : Print your ID\n"); + wprintw(self->window, " quit/exit : Exit program\n"); + wprintw(self->window, " help : Print this message again\n"); + wprintw(self->window, " clear : Clear this window\n"); + + wattron(self->window, A_BOLD); + wprintw(self->window, "TIP: Use the TAB key to navigate through the tabs.\n\n"); + wattroff(self->window, A_BOLD); + + wattroff(self->window, COLOR_PAIR(2)); +} + +void cmd_msg(ToxWindow *self, char **args) +{ + char *id = args[1]; + char *msg = args[2]; + if (m_sendmessage(atoi(id), (uint8_t*) msg, strlen(msg)+1) == 0) + wprintw(self->window, "Error occurred while sending message.\n"); + else + wprintw(self->window, "Message successfully sent.\n"); +} + +void cmd_myid(ToxWindow *self, char **args) +{ + char id[KEY_SIZE_BYTES*2 + 1] = {0}; + size_t i; + for (i = 0; i < KEY_SIZE_BYTES; ++i) { + char xx[3]; + snprintf(xx, sizeof(xx), "%02x", self_public_key[i] & 0xff); + strcat(id, xx); + } + wprintw(self->window, "Your ID: %s\n", id); +} + +void cmd_nick(ToxWindow *self, char **args) +{ + char *nick = args[1]; + setname((uint8_t*) nick, strlen(nick)+1); + wprintw(self->window, "Nickname set to: %s\n", nick); +} + +void cmd_status(ToxWindow *self, char **args) +{ + char *status = args[1]; + char *status_text; + + USERSTATUS status_kind; + if (!strncmp(status, "online", strlen("online"))) { + status_kind = USERSTATUS_NONE; + status_text = "ONLINE"; + } + else if (!strncmp(status, "away", strlen("away"))) { + status_kind = USERSTATUS_AWAY; + status_text = "AWAY"; + } + else if (!strncmp(status, "busy", strlen("busy"))) { + status_kind = USERSTATUS_BUSY; + status_text = "BUSY"; + } + else + { + wprintw(self->window, "Invalid status.\n"); + return; + } + + char *msg = args[2]; + if (msg == NULL) { + m_set_userstatus(status_kind); + wprintw(self->window, "Status set to: %s\n", status_text); + } + else { + m_set_userstatus(status_kind); + m_set_statusmessage((uint8_t*) msg, strlen(msg)+1); + wprintw(self->window, "Status set to: %s, %s\n", status_text, msg); + } +} + +void cmd_statusmsg(ToxWindow *self, char **args) +{ + char *msg = args[1]; + m_set_statusmessage((uint8_t*) msg, strlen(msg)+1); + wprintw(self->window, "Status set to: %s\n", msg); +} + static void execute(ToxWindow *self, char *u_cmd) { int newlines = 0; @@ -62,237 +299,43 @@ static void execute(ToxWindow *self, char *u_cmd) if (!isspace(cmd[cmd_end])) break; cmd[cmd_end + 1] = '\0'; - -/* What is this supposed to do? - if (cmd[0] == '/') { - wprintw(self->window,"Warning: Run your command without the /, this may not work\n"); - int i; - for (i = 1; i < strlen(cmd); i++) { //This doesn't work when it doesn't end with a space and another word - cmd[i - 1] = cmd[i]; //Still working on why - } - } -*/ - if (!strcmp(cmd, "quit") || !strcmp(cmd, "exit") || !strcmp(cmd, "q")) { - endwin(); - exit(0); - } + char *args[4]; + args[0] = strtok(cmd, " "); - else if (!strncmp(cmd, "connect ", strlen("connect "))) { - IP_Port dht; - char *ip = strchr(cmd, ' '); - if (ip == NULL) { - wprintw(self->window, "Invalid syntax.\n"); - return; - } - ip++; + /* no input */ + if (!args[0]) + return; - char *port = strchr(ip, ' '); - if (port == NULL) { - wprintw(self->window, "Invalid syntax.\n"); - return; - } - port[0] = 0; - port++; - - char *key = strchr(port, ' '); - if (key == NULL) { - wprintw(self->window, "Invalid syntax.\n"); - return; - } - key[0] = 0; - key++; - - if (atoi(port) == 0) { - wprintw(self->window, "Invalid syntax.\n"); - return; - } - - dht.port = htons(atoi(port)); - uint32_t resolved_address = resolve_addr(ip); - if (resolved_address == 0) { - return; - } - - dht.ip.i = resolved_address; - unsigned char *binary_string = hex_string_to_bin(key); - DHT_bootstrap(dht, binary_string); - free(binary_string); - } - - else if (!strncmp(cmd, "add ", strlen("add "))) { - uint8_t id_bin[KEY_SIZE_BYTES]; - char xx[3]; - uint32_t x; - char *id = strchr(cmd, ' '); - if (id == NULL) { - wprintw(self->window, "Invalid syntax.\n"); - return; - } - id++; - char *msg = strchr(id, ' '); - if (msg != NULL) { - msg[0] = 0; - msg++; - } - else msg = ""; - if (strlen(id) != 2*KEY_SIZE_BYTES) { - wprintw(self->window, "Invalid ID length.\n"); - return; - } - int i; - for (i = 0; i < KEY_SIZE_BYTES; ++i) { - xx[0] = id[2*i]; - xx[1] = id[2*i+1]; - xx[2] = '\0'; - if (sscanf(xx, "%02x", &x) != 1) { - wprintw(self->window, "Invalid ID.\n"); + /* match input to command list */ + for (i = 0; i < NUM_COMMANDS; i++) { + if (!strcmp(args[0], commands[i].name)) { + /* read in arguments */ + int j; + for (j = 1; j <= commands[i].numargs; j++) { + args[j] = strtok(NULL, " "); + /* check for missing arguments */ + /* add is special because it can take either 1 or 2 arguments */ + if (strcmp(args[0], "add") != 0 && args[j] == NULL) { + wprintw(self->window, "Invalid command: %s expected %d arguments, got %d.\n", + commands[i].name, commands[i].numargs, j - 1); + return; + } + } + /* check for excess arguments */ + /* add is special because the add message may contain spaces */ + if (strcmp(args[0], "add") != 0 && strtok(NULL, " ") != NULL) { + wprintw(self->window, "Invalid command: too many arguments to %s.\n", commands[i].name); return; } - id_bin[i] = x; - } - int num = m_addfriend(id_bin, (uint8_t*) msg, strlen(msg)+1); - switch (num) { - case -1: - wprintw(self->window, "Message is too long.\n"); - break; - case -2: - wprintw(self->window, "Please add a message to your request.\n"); - break; - case -3: - wprintw(self->window, "That appears to be your own ID.\n"); - break; - case -4: - wprintw(self->window, "Friend request already sent.\n"); - break; - case -5: - wprintw(self->window, "Undefined error when adding friend.\n"); - break; - default: - wprintw(self->window, "Friend added as %d.\n", num); - on_friendadded(num); - break; - } - } - - else if (!strcmp(cmd, "clear")) { - wclear(self->window); - } - - else if (!strcmp(cmd, "help")) { - wclear(self->window); - print_usage(self); - } - - else if (!strncmp(cmd, "status ", strlen("status "))) { - char *status = strchr(cmd, ' '); - char *msg; - char *status_text; - if (status == NULL) { - wprintw(self->window, "Invalid syntax.\n"); + /* pass arguments to command function */ + (commands[i].func)(self, args); return; } - status++; - USERSTATUS status_kind; - if (!strncmp(status, "online", strlen("online"))) { - status_kind = USERSTATUS_NONE; - status_text = "ONLINE"; - } - - else if (!strncmp(status, "away", strlen("away"))) { - status_kind = USERSTATUS_AWAY; - status_text = "AWAY"; - } - - else if (!strncmp(status, "busy", strlen("busy"))) { - status_kind = USERSTATUS_BUSY; - status_text = "BUSY"; - } - - else - { - wprintw(self->window, "Invalid status.\n"); - return; - } - - msg = strchr(status, ' '); - if (msg == NULL) { - m_set_userstatus(status_kind); - wprintw(self->window, "Status set to: %s\n", status_text); - } - else { - msg++; - m_set_userstatus(status_kind); - m_set_statusmessage((uint8_t*) msg, strlen(msg)+1); - wprintw(self->window, "Status set to: %s, %s\n", status_text, msg); - } } - else if (!strncmp(cmd, "nick ", strlen("nick "))) { - char *nick = strchr(cmd, ' '); - if (nick == NULL) { - wprintw(self->window, "Invalid syntax.\n"); - return; - } - nick++; - setname((uint8_t*) nick, strlen(nick)+1); - wprintw(self->window, "Nickname set to: %s\n", nick); - } - - else if (!strcmp(cmd, "myid")) { - char id[KEY_SIZE_BYTES*2 + 1] = {0}; - size_t i; - for (i = 0; i < KEY_SIZE_BYTES; ++i) { - char xx[3]; - snprintf(xx, sizeof(xx), "%02x", self_public_key[i] & 0xff); - strcat(id, xx); - } - wprintw(self->window, "Your ID: %s\n", id); - } - - else if (!strncmp(cmd, "accept ", strlen("accept "))) { - char *id = strchr(cmd, ' '); - if (id == NULL) { - wprintw(self->window, "Invalid syntax.\n"); - return; - } - id++; - - int num = atoi(id); - if (num >= num_requests) { - wprintw(self->window, "Invalid syntax.\n"); - return; - } - - num = m_addfriend_norequest(pending_requests[num]); - if (num == -1) - wprintw(self->window, "Failed to add friend.\n"); - else { - wprintw(self->window, "Friend accepted as: %d.\n", num); - on_friendadded(num); - } - } - - else if (!strncmp(cmd, "msg ", strlen("msg "))) { - char *id = strchr(cmd, ' '); - if (id == NULL) { - wprintw(self->window, "Invalid syntax.\n"); - return; - } - char *msg = strchr(++id, ' '); - if (msg == NULL) { - wprintw(self->window, "Invalid syntax.\n"); - return; - } - msg[0] = 0; - msg++; - if (m_sendmessage(atoi(id), (uint8_t*) msg, strlen(msg)+1) == 0) - wprintw(self->window, "Error occurred while sending message.\n"); - else - wprintw(self->window, "Message successfully sent.\n"); - } - else - wprintw(self->window, "Invalid command.\n"); + /* no match */ + wprintw(self->window, "Invalid command.\n"); } static void prompt_onKey(ToxWindow *self, int key) @@ -352,33 +395,10 @@ static void prompt_onDraw(ToxWindow *self) wrefresh(self->window); } -static void print_usage(ToxWindow *self) -{ - wattron(self->window, COLOR_PAIR(2) | A_BOLD); - wprintw(self->window, "Commands:\n"); - wattroff(self->window, A_BOLD); - - wprintw(self->window, " connect : Connect to DHT server\n"); - wprintw(self->window, " add : Add friend\n"); - wprintw(self->window, " status : Set your status\n"); - wprintw(self->window, " nick : Set your nickname\n"); - wprintw(self->window, " accept : Accept friend request\n"); - wprintw(self->window, " myid : Print your ID\n"); - wprintw(self->window, " quit/exit : Exit program\n"); - wprintw(self->window, " help : Print this message again\n"); - wprintw(self->window, " clear : Clear this window\n"); - - wattron(self->window, A_BOLD); - wprintw(self->window, "TIP: Use the TAB key to navigate through the tabs.\n\n"); - wattroff(self->window, A_BOLD); - - wattroff(self->window, COLOR_PAIR(2)); -} - static void prompt_onInit(ToxWindow *self) { scrollok(self->window, 1); - print_usage(self); + cmd_help(self, NULL); wclrtoeol(self->window); }