311 lines
6.8 KiB
C
311 lines
6.8 KiB
C
/* 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 <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "parse.h"
|
|
#include "error.h"
|
|
#include "help.h"
|
|
|
|
#define PARAMS_COUNT 5
|
|
|
|
enum cred_param_ids_e
|
|
{
|
|
USERNAME,
|
|
PASSWORD,
|
|
CHANNEL,
|
|
SERVER,
|
|
PORT
|
|
};
|
|
|
|
char const * cred_names[] =
|
|
{
|
|
"username",
|
|
"password",
|
|
"channel",
|
|
"server",
|
|
"port"
|
|
};
|
|
|
|
size_t const cred_names_len[] =
|
|
{
|
|
8,
|
|
8,
|
|
7,
|
|
6,
|
|
4
|
|
};
|
|
|
|
creds_t creds = {0};
|
|
char ** admins = NULL;
|
|
|
|
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); }
|
|
fclose(fp);
|
|
b[len+1] = '\0';
|
|
|
|
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)
|
|
{
|
|
f = 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) // TODO: implement
|
|
{
|
|
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 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
|
|
parse_admin_list(char const * admin_list_path)
|
|
{
|
|
#define ADMIN_LIST_INIT_SIZE 8
|
|
/* prealloc with 8 */
|
|
size_t current_array_size = ADMIN_LIST_INIT_SIZE;
|
|
|
|
FILE * stream;
|
|
size_t lines_read = 0;
|
|
char * line = NULL;
|
|
size_t nread = 0;
|
|
|
|
stream = fopen(admin_list_path, "r");
|
|
if (stream == NULL)
|
|
{
|
|
/* Pretty valid case I guess? No admin file = no admins,
|
|
maybe all configuration is performed locally */
|
|
return 0;
|
|
}
|
|
|
|
admins = calloc(ADMIN_LIST_INIT_SIZE, sizeof(char *));
|
|
|
|
while (getline(&line, &nread, stream) > 0)
|
|
{
|
|
if (++lines_read > current_array_size)
|
|
{
|
|
/* double the space */
|
|
current_array_size *= 2;
|
|
realloc(admins, current_array_size);
|
|
}
|
|
|
|
admins[lines_read - 1] = line;
|
|
}
|
|
|
|
/* set up array end marker for proper clean-up later */
|
|
if (lines_read + 1 > current_array_size)
|
|
{
|
|
realloc(admins, current_array_size + 1);
|
|
}
|
|
admins[lines_read] = NULL;
|
|
|
|
return 0;
|
|
}
|
|
|
|
DECL int
|
|
is_admin(char const * user)
|
|
{
|
|
/* No Gods or Kings, Only Man */
|
|
if (admins == NULL)
|
|
{ return 0; }
|
|
|
|
for (size_t i = 0; admins[i]; ++i)
|
|
{
|
|
if (!strcmp(admins[i], user))
|
|
{ return 1; }
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#define FREE(obj) \
|
|
do \
|
|
{ \
|
|
free(obj); \
|
|
(obj) = NULL; \
|
|
} while (0)
|
|
|
|
#define FULL_FREE(obj) \
|
|
do \
|
|
{ \
|
|
if ((obj)) \
|
|
{ \
|
|
memset((obj), '\0', strlen((obj))); \
|
|
FREE((obj)); \
|
|
} \
|
|
} while (0)
|
|
|
|
DECL void
|
|
clean_admin_list()
|
|
{
|
|
if (admins == NULL)
|
|
{ return; }
|
|
|
|
for (size_t i = 0; admins[i]; ++i)
|
|
{ free(admins[i]); }
|
|
|
|
FREE(admins);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
#undef FREE
|
|
#undef FULL_FREE
|