diff options
| author | Emil | 2023-08-04 09:13:47 -0600 |
|---|---|---|
| committer | Emil | 2023-08-04 09:13:47 -0600 |
| commit | 935243d8b4ea992c50315f0c8fcb300365a5762d (patch) | |
| tree | c22d800773997b7b267d5d6cba5931f22ee2be64 /src/parse.c | |
| download | emil-probotic-master.tar.xz emil-probotic-master.tar.zst | |
Diffstat (limited to 'src/parse.c')
| -rw-r--r-- | src/parse.c | 278 |
1 files changed, 278 insertions, 0 deletions
diff --git a/src/parse.c b/src/parse.c new file mode 100644 index 0000000..1e110b6 --- /dev/null +++ b/src/parse.c @@ -0,0 +1,278 @@ +/* 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. + + You should have received a copy of the GNU General Public License + version 3 along with Probotic. + +*/ + +#define PARAMS_COUNT 6 + +enum cred_names_map +{ + DATABASE, + USERNAME, + PASSWORD, + CHANNEL, + SERVER, + PORT +}; + +VARDECL char const * cred_names[] = +{ + "database", + "username", + "password", + "channel", + "server", + "port" +}; + +VARDECL size_t const cred_names_len[] = +{ + 8, + 8, + 8, + 7, + 6, + 4, + 6 +}; + +VARDECL creds_t creds = {0}; + +DECL char ** +str_split(char const * s, char c) +{ + char ** ret = NULL; + size_t i = 0; + + size_t current_token_i = 0; + + size_t token_start_i = 0; + size_t tokens_q = 0; + + /* count tokens */ + for (i = 1; s[i]; ++i) + { + /* end of a token*/ + if (s[i] == c && s[i - 1] != c) + { ++tokens_q; } + } + ++tokens_q; + + ret = (char **)calloc(tokens_q + 1, sizeof(char *)); + if (!ret) + { return ret; } + + for (i = 1; s[i]; ++i) + { + + if ((s[i + 1] == c || !s[i + 1]) && s[i] != c) + { + /* end of a token*/ + ret[current_token_i] = strndup(s + token_start_i, i - token_start_i + 1); + if (!ret[current_token_i]) + { + split_clean(ret); + return NULL; + } + ++current_token_i; + } + else if (s[i] != c && s[i - 1] == c) + { + /* start of a token */ + token_start_i = i; + } + } + + /* Signal that the split array is ended (for iteration purposes) */ + ret[current_token_i + 1] = NULL; + + return ret; +} + +DECL void +split_clean(char ** split) +{ + while (*split) + { + free(*split); + } + free(split); +} + +DECL char * +slurp(char const * 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+2); + if (b) + { + fread(b, 1, len, fp); + b[len+1] = '\0'; + } + fclose(fp); + + return b; + } + else + { return NULL; } +} + +DECL void +parse_command(char const * cmd) +{ + size_t i = 0; + char* msgswp = NULL; + /* 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, "kill") == 0) + { exit(1); } + if (strcmp(cmd, "remind") == 0) + { + msgswp = remind(current_username); + ircmsg("%s: %s", current_username, msgswp); + } + /* XXX: maybe no? */ + /*else if (strcmp(cmd, "next") == 0) | TODO: implement */ + /* { ircmsg("%s: No future assignments", current_username); } */ + else if (strcmp(cmd, "help") == 0) + { ircmsg(help_msg); } + else if (strcmp(cmd, "magic") == 0) + { stupid_shit = 8 + (rand() % 100); } + else if (strcmp(cmd, "dump") == 0) + { + ircmsg("%s: All projects:", current_username); + msgswp = dump(); + ircmsg(msgswp); + } + else if (strcmp(cmd, "reroll") == 0) + { + ircmsg("%s: Rerolling...", current_username); + purge_assignments(current_username); + random_assign(current_username); + ircmsg(remind(current_username)); + } + } + else + { + /* some arguments */ + char const * const arg = cmd + i + 1; + if (strncmp(cmd, "raw", i) == 0) + { + ircmsg("%s: Executing SQL `%s'.", current_username, arg); + msgswp = raw(arg); + ircmsg(msgswp); + } + else if (strncmp(cmd, "set_repo", i) == 0) + { + ircmsg("%s: Setting project repository...", current_username); + set_repo(creds.channel, arg); + msgswp = remind(creds.channel); + ircmsg("%s: %s", current_username, msgswp); + } + /* XXX: what is this suppose to do? */ + else if (strncmp(cmd, "submit", i) == 0) /* TODO: implement */ + { + ircmsg("%s: Submitting project link '%s' to <random janny>", + current_username, arg); + } + } + free(msgswp); +} + +DECL int +parse_pair(char const * buf, size_t len) +{ + size_t i, f, x; + /* fprintf(stderr, "ENT len:%ld buf:%sEOF\n", len, buf); */ + for (i = 0; buf[i] && + i < len; ++i) + { + if (buf[i] == '=') + { + ++i; + for (f = 0, x = 0; f < PARAMS_COUNT; ++f) + { + /* fprintf(stderr, "x%ld, i%ld, %s\n", x, i, buf); */ + /* X macro for handling this data may be better */ + if (strncmp(buf, cred_names[f], cred_names_len[f]) == 0) + { + /* fprintf(stderr, "f%ld:len%ld:%s\n", f, cred_names_len[f], */ + /* cred_names[f]); fflush(stderr); */ + buf += i; + while (buf[x] != '\0') + { + if (buf[x] == '\n') + { + len -= i; i = 0; break; + } + ++x; + } + switch (f) + { + case DATABASE: db = strndup(buf,x); break; + 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); break; + } + if (x + 2 < len) + { buf += x + 1; } + else + { return 1; } + goto next; + } + } + } + next:; + } + return 0; +} + +DECL int +is_admin(char const * user) +{ + /* No Gods or Kings, Only size_t */ + return 1; +} + +void +creds_free_password(void) +{ + FULL_FREE(creds.password); +} + +void +creds_free_rest(void) +{ + FULL_FREE(creds.username); + /* FULL_FREE(creds.password); */ + FULL_FREE(creds.channel); + FULL_FREE(creds.server); + FREE(creds.admins); +} |
