aboutsummaryrefslogtreecommitdiff
path: root/src/parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/parse.c')
-rw-r--r--src/parse.c278
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);
+}