Working on uthash

This commit is contained in:
Emil 2023-09-24 17:05:28 +00:00
parent 0a0a7bbaa9
commit 5c56c20c60
No known key found for this signature in database
GPG Key ID: 5432DB986FDBCF8A
5 changed files with 189 additions and 141 deletions

View File

@ -1,10 +1,10 @@
PROGN:=probotic TARGET:=probotic
USER := probotic USER := probotic
PREFIX = /opt/${USER}/ PREFIX = /opt/${USER}/
CFLAGS:=-std=c99 -Wall -Wextra -Wpedantic -Wvla -Wshadow -Wundef CFLAGS:=-std=c99 -Wall -Wextra -Wpedantic -Wvla -Wshadow -Wundef
CPPFLAGS:=-I./lib/libircclient/include/ -Iinclude -D_GNU_SOURCE -DPROGN=\"${PROGN}\" -D_FORTIFY_SOURCE=2 CPPFLAGS:=-I./lib/libircclient/include/ -Iinclude -D_GNU_SOURCE -D_FORTIFY_SOURCE=2 -DPROGN=\"${TARGET}\"
LDLIBS:=-lsqlite3 LDLIBS:=-lsqlite3
LIB:=./lib/libircclient/src/libircclient.o LIB:=./lib/libircclient/src/libircclient.o
@ -28,7 +28,7 @@ ifeq (${ENABLE_SSL},1)
LDLIBS += -lssl -lcrypto LDLIBS += -lssl -lcrypto
endif endif
${PROGN}: include/config.h ${HDR} ${SRC} ${TARGET}: include/config.h ${HDR} ${SRC}
${LINK.c} -pipe ${LIB} src/unity.c -o $@ ${LDLIBS} ${LINK.c} -pipe ${LIB} src/unity.c -o $@ ${LDLIBS}
# do nothing but update them... # do nothing but update them...
@ -38,7 +38,7 @@ include/config.h: config.mk.h
cp -f $< $@ cp -f $< $@
clean: clean:
-rm ${OBJ} -rm ${TARGET}
${PREFIX}: ${PREFIX}:
mkdir $@ mkdir $@
@ -47,8 +47,8 @@ bootstrap:
make -C bootstrap make -C bootstrap
install: bootstrap ${PREFIX} install: bootstrap ${PREFIX}
useradd ${USER} -r -s /sbin/nologin -d ${PREFIX} || true useradd ${USER} -r -s /sbin/nologin -d ${PREFIX} || true # Bypass "Already Exists"
install -v -g ${USER} -o ${USER} -m 744 ./bootstrap/data.sqlite ${PROGN} ${PREFIX} install -v -g ${USER} -o ${USER} -m 744 ./bootstrap/data.sqlite ${TARGET} ${PREFIX}
chown ${USER}:${USER} ${PREFIX} -R chown ${USER}:${USER} ${PREFIX} -R
uninstall: uninstall:

View File

@ -10,3 +10,6 @@
/* Enables SSL support /* Enables SSL support
* FIXME broken at the moment */ * FIXME broken at the moment */
/* #define IRC_SSL_SUPPORT */ /* #define IRC_SSL_SUPPORT */
/* the bot that encompasses secondary users */
/* #define SECONDARY_NAMES_BOT "nil" */

262
src/irc.c
View File

@ -4,8 +4,6 @@
#define IRCMSG(msg) irc_cmd_msg(session, creds.channel, msg) #define IRCMSG(msg) irc_cmd_msg(session, creds.channel, msg)
#define MAX(a,b) (a) > (b)
typedef struct typedef struct
{ {
char * username; char * username;
@ -15,6 +13,13 @@ typedef struct
int port; int port;
} creds_t; } creds_t;
typedef struct
{
const char * key;
int val;
UT_hash_handle hh;
} map_t;
VARDECL creds_t creds = VARDECL creds_t creds =
{ {
.username = NULL, .username = NULL,
@ -28,6 +33,8 @@ VARDECL creds_t creds =
#endif /* !IRC_SSL_SUPPORT */ #endif /* !IRC_SSL_SUPPORT */
}; };
VARDECL map_t * map = NULL;
VARDECL char * ident_password = NULL; VARDECL char * ident_password = NULL;
VARDECL irc_session_t * session; VARDECL irc_session_t * session;
@ -45,12 +52,16 @@ IRC_GREEN "!reroll " IRC_STOP " : Rerolls assignment\n"
/* IRC_GREEN "!request " IRC_STOP " : Request personal project\n" */ /* IRC_GREEN "!request " IRC_STOP " : Request personal project\n" */
IRC_GREEN "!remind " IRC_STOP " : Prints your assignment\n" IRC_GREEN "!remind " IRC_STOP " : Prints your assignment\n"
IRC_GREEN "!poll " IRC_STOP " : Start the democratic process (N message ...])\n" IRC_GREEN "!poll " IRC_STOP " : Start the democratic process (N message ...])\n"
IRC_GREEN "!vote " IRC_STOP " : Casts a vote (y/n [message ...])\n" IRC_GREEN "!y " IRC_STOP " : Votes yes\n"
IRC_GREEN "!n " IRC_STOP " : Votes no\n"
IRC_GREEN "!stop " IRC_STOP " : Stop the current polling\n" IRC_GREEN "!stop " IRC_STOP " : Stop the current polling\n"
IRC_BLUE "!magic " IRC_STOP " : A random value at or below 100 or (N)\n"; IRC_BLUE "!magic " IRC_STOP " : (N) Who knows.\n"
IRC_GREEN "!dice " IRC_STOP " : (N or AdX format) Rolls dice.";
DECL void parse_command(char const * cmd); DECL void parse_command(char * cmd);
#ifdef SECONDARY_NAMES_BOT
DECL size_t parse_secondary_username(char const * msg); DECL size_t parse_secondary_username(char const * msg);
#endif /* SECONDARY_NAMES_BOT */
DECL char * DECL char *
get_username(const char * origin) get_username(const char * origin)
@ -132,13 +143,13 @@ event_connect(irc_session_t * lsession,
DECL void DECL void
event_channel(irc_session_t * lsession, event_channel(irc_session_t * lsession,
char const * event, char * event,
char const * origin, char * origin,
char const ** params, char ** params,
unsigned int count) unsigned int count)
{ {
/* char const * channel = params[0]; */ /* char const * channel = params[0]; */
char const * message = params[1]; char * message = params[1];
(void) lsession; (void) lsession;
(void) event; (void) event;
(void) origin; (void) origin;
@ -149,7 +160,9 @@ event_channel(irc_session_t * lsession,
{ return; } { return; }
printf("<%s> %s\n", current_username, message); printf("<%s> %s\n", current_username, message);
/* Detects any respecified names */ /* Detects any respecified names */
/* message += parse_secondary_username(message); */ #ifdef SECONDARY_NAMES_BOT
message += parse_secondary_username(message);
#endif /* SECONDARY_NAMES_BOT */
/* Parse commands */ /* Parse commands */
if (*message == PREFIX_COMMAND_CHAR && if (*message == PREFIX_COMMAND_CHAR &&
message[1] != '\0') message[1] != '\0')
@ -158,9 +171,53 @@ event_channel(irc_session_t * lsession,
current_username = NULL; current_username = NULL;
} }
/* 'abc' SINGLE int name_sort(const map_t * a,
'def ' SINGLE const map_t * b)
'ghi jkl' MULTI */ {
return strcmp(a->key, b->key);
}
DECL void
parse_command_init(void)
{
size_t i;
static const char * commands[] =
{
"n", /* 0 */
"remind", /* 1 */
"y", /* 2 */
"help", /* 3 */
"magic", /* 4 */
"dice", /* 5 */
"reroll", /* 6 */
"poll", /* 7 */
"stop", /* 8 */
NULL
};
map_t * s;
for (i = 0; commands[i]; ++i)
{
s = (map_t *) malloc(sizeof(map_t));
s->key = strdup(commands[i]);
s->val = i;
HASH_ADD_STR(map, key, s);
}
HASH_SORT(map, name_sort);
}
DECL void
parse_command_free(void)
{
map_t * s, * tmp;
HASH_ITER(hh, map, s, tmp) {
HASH_DEL(map, s);
free((void*)s->key);
free(s);
}
}
#define DICE_DEFAULT 6
#define ARGMASK 16
DECL int DECL int
has_arg(char const * cmd) has_arg(char const * cmd)
@ -169,12 +226,12 @@ has_arg(char const * cmd)
while (isalnum(*cmd)) while (isalnum(*cmd))
{ {
if (*cmd == '\0') if (*cmd == '\0')
{ break; } { return 0; }
++cmd; ++cmd;
} }
while (*cmd != '\0') while (*cmd != '\0')
{ {
if (!isspace(*cmd)) if (isspace(*cmd))
{ return cmd - start; } { return cmd - start; }
++cmd; ++cmd;
} }
@ -182,117 +239,98 @@ has_arg(char const * cmd)
} }
DECL void DECL void
parse_command(char const * cmd) parse_command(char * cmd)
{ {
static int vote_count; static int vote_count, vote;
int dice = DICE_DEFAULT;
size_t len = has_arg(cmd);
size_t i = 0; size_t i = 0;
char * msgswp = NULL; char x;
/* size_t len = strlen(cmd); */ char * arg = NULL;
if (!(i = has_arg(cmd))) char * msgswp;
map_t * s;
/* x = cmd[len]; */
/* fprintf(stderr, "%ld\n", len); */
/* cmd[len] = cmd[len] != '\0' ? '\0' : cmd[len]; */
/* HASH_FIND_STR(map, cmd, s); */
/* fprintf(stderr, "cmd: "); */
/* while (cmd[i]) */
/* { */
/* x = cmd[len]; */
/* cmd[len] = cmd[len] ? cmd[len] : '\0'; */
/* fprintf(stderr, "%c:%d ", cmd[i], cmd[i]); */
/* ++i; */
/* } */
/* cmd[len] = x; */
/* putchar('\n'); */
x = cmd[len];
if (len &&
cmd[len] != 0)
{ cmd[len] = '\0'; }
HASH_FIND_STR(map, cmd, s);
cmd[len] = x;
if (cmd[len])
{ {
printf("NARG Handling '%s'\n", cmd); arg = cmd + len;
/* NO ARGUMENTS */ }
if (strncmp(cmd, "remind", 6) == 0) if (arg) { fprintf(stderr, "arg: '%s'\n", arg); }
if (s)
{
if (arg) {s->val |= ARGMASK; }
switch (s->val)
{ {
case 0 : /* n */
case 2 : /* y */
vote = s->val - 1; /* I had to, man */
if (--vote_count)
{ ircmsg(creds.channel, "Votes remaining: %d", vote_count); }
else
{ ircmsg(creds.channel,
"poll: %s",
vote == 0 ? "UNDECIDED" :
vote > 0 ? "PASSED" :
"REJECTED"); }
break;
case 1 : /* remind */
msgswp = remind(current_username); msgswp = remind(current_username);
ircmsg(creds.channel, "%s: %s", current_username, msgswp); ircmsg(creds.channel, "%s: %s", current_username, msgswp);
} break;
else if (strncmp(cmd, "help", 4) == 0) case 3 : /* help */
{ ircmsg(creds.channel, help_msg); } ircmsg(creds.channel, help_msg);
else if (strncmp(cmd, "magic", 5) == 0) break;
{ ircmsg(creds.channel, "%s: " IRC_YELLOW "%d" IRC_STOP, current_username, (rand() % 100) + 1); } case 4 : /* magic */
#ifndef NO_VULN_COMMANDS break;
else if (strncmp(cmd, "dump", 4) == 0) case 5 | 16 :
{ dice = atoi(arg);
ircmsg(creds.channel, "%s: All projects:", current_username); /* fallthrough */
msgswp = dump(); case 5 : /* dice */
ircmsg(creds.channel, msgswp); ircmsg(creds.channel, "%s: " IRC_YELLOW "%d" IRC_STOP, current_username, (rand() % dice) + 1);
} break;
#endif /* !NO_VULN_COMMANDS */ case 6 : /* reroll */
else if (strncmp(cmd, "reroll", 6) == 0)
{
purge_assignments(current_username); purge_assignments(current_username);
random_assign(current_username); random_assign(current_username);
ircmsg(creds.channel, "%s: %s", current_username, remind(current_username)); ircmsg(creds.channel, "%s: %s", current_username, remind(current_username));
} break;
else if (strncmp(cmd, "stop", 4) == 0) case 7 | ARGMASK : /* poll */
{ vote = 0;
vote_count = atoi(arg);
if (!vote_count)
case 7 : { ircmsg(creds.channel, "!poll NUMBER_OF_VOTES, What you're voting on"); }
else
{ ircmsg(creds.channel, "poll: start, vote with !y or !n"); }
break;
case 8 : /* stop */
if (vote_count) if (vote_count)
{ {
ircmsg(creds.channel, "poll: stop"); ircmsg(creds.channel, "poll: stop");
vote_count = 0; vote_count = 0;
} }
break;
default:
fprintf(stderr, "Unhandled match.\n");
} }
} }
else /* HAS ARGUMENTS */
{
printf("ARG Handling '%s'\n", cmd);
static int yes, no;
char const * const arg = cmd + i;
/* fprintf(stderr, "argoff: %p; i: %ld; arg: %sEOA\n", cmd + i + 1, i, arg); */
#ifndef NO_VULN_COMMANDS
if (strncmp(cmd, "raw", 3) == 0)
{
printf("RAW\n");
ircmsg(creds.channel, "%s: Executing SQL `%s'.", current_username, arg);
msgswp = raw(arg);
ircmsg(creds.channel, msgswp);
} else
#endif /* !NO_VULN_COMMANDS */
#if 0
if (strncmp(cmd, "repo", 4) == 0)
{
/* ircmsg(creds.channel, "%s: Setting project repository...", current_username); */
set_repo(creds.channel, arg);
msgswp = remind(creds.channel);
ircmsg(creds.channel, "%s: %s", current_username, msgswp);
}
#endif /* 0 */
if (strncmp(cmd, "magic", 5) == 0)
{ ircmsg(creds.channel, "%s: " IRC_YELLOW "%d" IRC_STOP, current_username, (rand() % atoi(arg)) + 1); }
else if (strncmp(cmd, "echo", 3) == 0)
{ ircmsg(creds.channel, "%s", arg); }
else if (strncmp(cmd, "poll", 4) == 0)
{
yes = no = 0;
vote_count = atoi(arg);
if (!vote_count)
{ ircmsg(creds.channel, "!poll NUMBER_OF_VOTES What your voting on ..."); }
else
{ ircmsg(creds.channel, "poll: start"); }
}
else if (strncmp(cmd, "vote", 4) == 0)
{
/* fprintf(stderr, "y%d n%d vote_count %d\n", yes, no, vote_count); */
if (vote_count)
{
switch (*arg)
{
case 'Y': case 'y': ++yes; break;
case 'N': case 'n': ++no; break;
default: ircmsg(creds.channel, "Unknown: '%c', use y/n", *arg); goto stop;
}
if (--vote_count)
{ ircmsg(creds.channel, "Votes remaining: %d", vote_count); }
else
{ ircmsg(creds.channel, "poll: %s", MAX(yes,no) ? "PASSED" : "REJECTED"); }
}
}
}
stop:
free(msgswp);
}
/* mutates current_username and returns positional offset to the first character that isn't related to the uname */
DECL size_t
parse_secondary_username(char const * msg)
{
int ret = 0;
#define SECONDARY_NAMES_BOT "cnile"
if (strcmp(current_username,SECONDARY_NAMES_BOT) == 0)
if (*msg == '<')
{ while (msg[++ret] != '\0' ||
msg[ret] != '>'); }
fprintf(stderr, "msg[ret] = %c", msg[ret]);
return ret;
} }

View File

@ -1,5 +1,28 @@
/* main.c */ /* main.c */
#define DECL static
#define VARDECL static
#include <assert.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <ctype.h>
#include <libircclient.h>
#include <sqlite3.h>
#include <uthash.h>
#include "error.h"
#include "irccolors.h"
#include "config.h"
#include "stmt.c"
#include "api.c"
#include "irc.c"
#define VERSION_STRING "2" #define VERSION_STRING "2"
/* Parses the format username[:password]@server[:port] /* Parses the format username[:password]@server[:port]
@ -43,6 +66,7 @@ rope(void)
if (session) if (session)
{ irc_destroy_session(session); } { irc_destroy_session(session); }
api_rope(); api_rope();
parse_command_free();
} }
/* All possible failures / successes wipe the password from memory. */ /* All possible failures / successes wipe the password from memory. */
@ -51,9 +75,14 @@ init(void)
{ {
int ret = 0; int ret = 0;
srand(time(NULL)); srand(time(NULL));
parse_command_init();
memset(&callbacks, 0, sizeof(callbacks)); memset(&callbacks, 0, sizeof(callbacks));
callbacks.event_connect = event_connect; callbacks.event_connect = event_connect;
callbacks.event_channel = event_channel; callbacks.event_channel = (void (*)(struct irc_session_s *,
const char *,
const char *,
const char **,
unsigned int)) event_channel;
if(!api_init()) if(!api_init())
{ {
session = irc_create_session(&callbacks); session = irc_create_session(&callbacks);

View File

@ -1,22 +0,0 @@
#define DECL static
#define VARDECL static
#include <assert.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <ctype.h>
#include <libircclient.h>
#include <sqlite3.h>
#include "error.h"
#include "irccolors.h"
#include "config.h"
#include "stmt.c"
#include "api.c"
#include "irc.c"
#include "main.c"