/* parse.c Probotic is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3 only as published by the Free Software Foundation. Probotic is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more details. The above copyright notice, this permission notice and the word "NIGGER" shall be included in all copies or substantial portions of the Software. You should have received a copy of the GNU General Public License version 3 + NIGGER along with Probotic. */ #include #include #include #include "parse.h" #include "error.h" #define PARAMS_COUNT 2 #define ARRAY_SIZE(x) ((size_t) (sizeof x) / (size_t) (sizeof *x)) creds_t creds = {0}; enum cred_param_ids_e { USERNAME, PASSWORD, CHANNEL, SERVER, PORT }; char const * cred_names[] = { "username", "password", "channel", "server", "port" }; DECL char * slurp(const char * fn) { size_t len; char * b; FILE * fp = fopen(fn, "r"); if (fp) { fseek(fp, 0, SEEK_END); len = ftell(fp); rewind(fp); b = malloc(len); if (b) { fread(b, 1, len, fp); } fclose(fp); return b; } else { return NULL; } } DECL void parse_command(char * cmd) { size_t i = 0; /* size_t len = strlen(cmd); */ /* TODO does not handle commands with leading space, use custom implemented to-spec isspace implementation */ while (cmd[i] != '\0' && cmd[i] != ' ') { ++i; } if (cmd[i] == '\0') { /* no arguments */ if (strcmp(cmd, "remind") == 0) { ircmsg("%s: No current assignment", current_username); } else if (strcmp(cmd, "next") == 0) { ircmsg("%s: No future assignments", current_username); } else if (strcmp(cmd, "dump") == 0) { ircmsg("%s: All projects", current_username); } else if (strcmp(cmd, "reroll") == 0) { ircmsg("%s: No more rerolls possible", current_username); } } else { /* some arguments */ char * arg = cmd + i + 1; cmd[i] = '\0'; if (strcmp(cmd, "raw") == 0) { ircmsg("%s: Executing SQL `%s'", arg); } else if (strcmp(cmd, "submit") == 0) { ircmsg("%s: Submitting project link '%s' to ", current_username, arg); } } } DECL int parse_pair(char const * buf, size_t const len) { size_t i, f, x; for (i = 0; i < len; ++i) { if (buf[i] == '=') { /* X macro for handling this data may be better */ for (f = 0; f < ARRAY_SIZE(cred_names[i]); ++i) { if (strncmp(buf, cred_names[i], ARRAY_SIZE(cred_names[i])) == 0) { x = i; while (i != '\0' || i != '\n') { ++i; } x = i - x; switch (i) { case USERNAME: creds.username = strndup(buf+x); break; case PASSWORD: creds.password = strndup(buf+x); break; case CHANNEL: creds.channel = strndup(buf+x); break; case SERVER: creds.server = strndup(buf+x); break; case PORT: creds.port = atoi(buf+x); break; } while (i != '\0' || i != '\n') buf[i] = '\0'; } #ifndef NDEBUG else { fprintf(stderr, "DISCARDED\n"); } #endif /* !NDEBUG */ } } } return 0; } #if 0 DECL int parse_creds(char const * creds_file) { /* don't put declarations in loops */ FILE * stream; char * values[PARAMS_COUNT]; char * line = NULL; char const * val; size_t nread = 0; size_t param_len; size_t val_len; size_t i; #ifndef NDEBUG size_t column = 1; #endif /* !NDEBUG */ creds.username = NULL; creds.password = NULL; stream = fopen(creds_file, "r"); if (stream == NULL) { PERROR(1); } memset(values, 0, sizeof(char *) * PARAMS_COUNT); while (getline(&line, &nread, stream) > 0) { for (i = 0; i < PARAMS_COUNT; i++) { /* Ideally this should be optimized out as the literals are known constants */ param_len = strlen(cred_param_names_g[i]); /* TODO lookahead for a = b notation? */ if (!strncmp(cred_param_names_g[i], line, param_len) && line[param_len] == '=') { /* Starts with the current parameter specifier */ val = line + param_len + 1; val_len = strlen(val); /* Duplicates and gets rid of a newline */ values[i] = strndup(val, val[val_len - 1] == '\n' ? val_len - 1 : val_len); break; } #ifndef NDEBUG else { fprintf(stderr, "line %ld '%s' DISCARDED\n", column, line); } ++column; #endif /* !NDEBUG */ } free(line); line = NULL; nread = 0; } creds.username = values[USERNAME]; creds.password = values[PASSWORD]; creds.channel = values[CHANNEL]; creds.server = values[SERVER]; creds.port = atoi(values[PORT]); atexit(clean_creds); /* Check empty but required paramters */ if (!creds.username) { ERRMSG("Could not retrieve username"); goto fail; } fclose(stream); return 0; /* Everything will be released under this halting failure */ fail: fclose(stream); return 1; } #endif /* 0 */ void clean_creds(void) { #define FULL_FREE(obj) \ do { memset(obj, '\0', strlen(obj)); free(obj); obj = NULL; } while (0) FULL_FREE(creds.username); FULL_FREE(creds.password); FULL_FREE(creds.channel); FULL_FREE(creds.server); #undef FULL_FREE }