Aggressive restructuring
This commit is contained in:
parent
937e2536f0
commit
ffb8c54644
13
Makefile
13
Makefile
@ -9,7 +9,9 @@ LDLIBS:=-lsqlite3
|
||||
LIB:=./lib/libircclient/src/libircclient.o
|
||||
|
||||
SRC := api.c irc.c main.c parse.c unity.c
|
||||
HDR := api.h error.h irc.h irccolors.h parse.h stmt.h
|
||||
HDR := config.h api.h error.h irc.h irccolors.h parse.h stmt.h
|
||||
|
||||
VPATH := src include
|
||||
|
||||
ifeq (${DEBUG},1)
|
||||
CFLAGS += -Og -ggdb
|
||||
@ -30,18 +32,21 @@ ifeq (${ENABLE_SSL},1)
|
||||
CPPFLAGS += -DIRC_SSL_SUPPORT
|
||||
endif
|
||||
|
||||
all: ${PROGN}
|
||||
all: include/config.h ${PROGN}
|
||||
|
||||
${PROGN}: ${HDR} ${SRC}
|
||||
${LINK.c} -pipe ${LIB} src/unity.c -o $@ ${LDLIBS}
|
||||
|
||||
# do nothing but update them...
|
||||
$(SRC) $(HDR):
|
||||
${SRC} ${HDR}:
|
||||
|
||||
submodules:
|
||||
git submodule update --init --recursive
|
||||
|
||||
include/config.h: config.mk.h
|
||||
cp -f $< $@
|
||||
|
||||
clean:
|
||||
-rm ${OBJ}
|
||||
|
||||
.PHONY: submodules clean
|
||||
.PHONY: all submodules clean
|
||||
|
30
build.sh
30
build.sh
@ -1,30 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Script handling unity builds and options.
|
||||
|
||||
DIR=$(dirname $(readlink -f "$0"))
|
||||
cd $DIR
|
||||
|
||||
PROGN=${PROGN:-probotic}
|
||||
PREFIX=${PREFIX:-$DIR}
|
||||
|
||||
CC=${CC-cc}
|
||||
CFLAGS='-std=c99 -Wall -Wextra -Wpedantic -Wno-unused-function'
|
||||
CPPFLAGS="-I/usr/include/libircclient/ -Iinclude -D_GNU_SOURCE -DPROGN=\"$PROGN\""
|
||||
LDFLAGS='-lircclient -lsqlite3'
|
||||
|
||||
mkdir -p $PREFIX && echo "Made directory: $PREFIX"
|
||||
|
||||
# Bourne shell is evil
|
||||
if [ ${DEBUG-0} -eq 1 ]
|
||||
then
|
||||
CFLAGS=`echo "${CFLAGS} -O0 -ggdb"`
|
||||
else
|
||||
CPPFLAGS="${CPPFLAGS} -DNDEBUG"
|
||||
CFLAGS=`echo "${CFLAGS} -O2 -flto=auto -fomit-frame-pointer -s"`
|
||||
fi
|
||||
|
||||
[ ! -z ${SAN} ] && CFLAGS=`echo "$CFLAGS -fsanitize=$SAN"`
|
||||
|
||||
echo "$CC $CFLAGS -pipe $DIR/src/unity.c -o $PREFIX/$PROGN $CPPFLAGS $LDFLAGS"
|
||||
time $CC $CFLAGS -pipe $DIR/src/unity.c -o $PREFIX/$PROGN $CPPFLAGS $LDFLAGS
|
||||
echo -e "\nStatus: $?"
|
@ -1,12 +0,0 @@
|
||||
#ifndef API_H_
|
||||
|
||||
VARDECL char const * db;
|
||||
|
||||
DECL int api_init(void);
|
||||
DECL void api_rope(void);
|
||||
DECL void rope(void);
|
||||
DECL char * remind(char * who);
|
||||
/* DECL int is_no_assignment(char const * const who); */
|
||||
|
||||
#define API_H_
|
||||
#endif
|
1
include/config.mk.h
Normal file
1
include/config.mk.h
Normal file
@ -0,0 +1 @@
|
||||
#define DBFILE "probotic_data.sqlite"
|
@ -1,7 +1,3 @@
|
||||
#ifndef ERROR_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define ERR(ret,msg) \
|
||||
do { fputs(PROGN ": " msg "\n", stderr); return (ret); } while (0)
|
||||
|
||||
@ -17,6 +13,3 @@
|
||||
#define DB_ERROR 100
|
||||
#define IRC_ERROR 101
|
||||
#define CREDS_ERROR 102
|
||||
|
||||
#define ERROR_H_
|
||||
#endif
|
||||
|
@ -1,22 +0,0 @@
|
||||
#ifndef FREE_H_
|
||||
|
||||
#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)
|
||||
|
||||
|
||||
#define FREE_H_
|
||||
#endif
|
@ -1,6 +0,0 @@
|
||||
#ifndef HELP_H_
|
||||
|
||||
VARDECL char const * help_msg;
|
||||
|
||||
#define HELP_H_
|
||||
#endif
|
@ -1,14 +0,0 @@
|
||||
#ifndef IRC_H_
|
||||
|
||||
#include <libircclient.h>
|
||||
|
||||
#include "parse.h"
|
||||
|
||||
VARDECL irc_session_t * session;
|
||||
VARDECL irc_callbacks_t callbacks;
|
||||
VARDECL char * current_username;
|
||||
|
||||
DECL int init(void);
|
||||
|
||||
#define IRC_H_
|
||||
#endif
|
@ -1,5 +1,3 @@
|
||||
#ifndef IRCCOLOR_H_
|
||||
|
||||
// Formatting macros
|
||||
#define IRC_BOLD "[B]"
|
||||
#define IRC_ITALIC "[I]"
|
||||
@ -22,6 +20,3 @@
|
||||
#define IRC_DARKGRAY "[COLOR=DARKGRAY]"
|
||||
#define IRC_LIGHTGRAY "[COLOR=LIGHTGRAY]"
|
||||
#define IRC_STOP "[/COLOR]"
|
||||
|
||||
#define IRCCOLOR_H_
|
||||
#endif
|
||||
|
@ -1,32 +0,0 @@
|
||||
#ifndef CREDS_PARSER_H
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char * username;
|
||||
char * password;
|
||||
char * channel;
|
||||
char * server;
|
||||
int port;
|
||||
} creds_t;
|
||||
|
||||
VARDECL creds_t creds;
|
||||
/* nickserv identify password */
|
||||
VARDECL char * ident_password = NULL;
|
||||
|
||||
/* DECL char ** str_split(char const * s, char c); */
|
||||
/* DECL void split_clean(char ** split); */
|
||||
/* DECL int is_admin(char const * user); */
|
||||
|
||||
#ifndef NO_VULN_COMMANDS
|
||||
DECL char * dump(void);
|
||||
DECL char * raw(char const * const sql);
|
||||
#endif /* !NO_VULN_COMMANDS */
|
||||
DECL char * remind(char * who);
|
||||
DECL void creds_free(void);
|
||||
DECL void parse_command(char const * const cmd);
|
||||
DECL void purge_assignments(char const * const who);
|
||||
DECL void random_assign(char const * const sql);
|
||||
DECL void set_repo(char const * const who, char const * const link);
|
||||
|
||||
#define CREDS_PARSER_H
|
||||
#endif
|
23
install.sh
23
install.sh
@ -1,13 +1,20 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "./uninstall.sh will destroy to whatever TARGET is set to, be careful!"
|
||||
|
||||
# VARIABLES AND PATH
|
||||
TARGET=${TARGET-/opt/probotic}
|
||||
DIR=$(dirname $(readlink -f "$0"))
|
||||
cd $DIR
|
||||
[ ! -e $DIR/probotic ] && make DEBUG=0 NVULN=1 || return 1
|
||||
# run bootstrapper
|
||||
[ ! -e $DIR/bootstrap/ ] && $DIR/bootstrap/bootstrap.sh || return 1
|
||||
# generate directories and install
|
||||
TARGET=${TARGET-/opt/probotic}
|
||||
useradd probotic -r -s /sbin/nologin -d $TARGET
|
||||
|
||||
# BUILD & BOOTSTRAP
|
||||
make -C $DIR DEBUG=0 NVULN=1 || exit 1
|
||||
$DIR/bootstrap/bootstrap.sh || exit 1
|
||||
|
||||
# INSTALL
|
||||
mkdir -p $TARGET
|
||||
install -g probotic -o probotic -m 744 \
|
||||
$DIR/bootstrap/probotic_data.sqlite probotic -v $TARGET
|
||||
useradd probotic -r -s /sbin/nologin -d $TARGET
|
||||
install -v -g probotic -o probotic -m 744 \
|
||||
$DIR/bootstrap/probotic_data.sqlite probotic \
|
||||
$TARGET
|
||||
chown probotic:probotic $TARGET -R
|
||||
|
40
src/api.c
40
src/api.c
@ -1,4 +1,4 @@
|
||||
#define DBFILE "probotic_data.sqlite"
|
||||
/* api.c - Database API */
|
||||
|
||||
#define stmt_prepare(stmt) \
|
||||
sqlite3_prepare_v2(connection, stmt ## _template, -1, &stmt, NULL)
|
||||
@ -22,7 +22,7 @@ DECL int
|
||||
api_init(void)
|
||||
{
|
||||
DBERR(sqlite3_open_v2(db, &connection, SQLITE_OPEN_READWRITE, NULL));
|
||||
// dont you fucking dare to remove this spacing
|
||||
/* dont you fucking dare to remove this spacing */
|
||||
DBERR(stmt_prepare(remind_stmt));
|
||||
DBERR(stmt_prepare(set_repo_stmt));
|
||||
DBERR(stmt_prepare(get_nth_id_stmt));
|
||||
@ -44,21 +44,13 @@ api_rope(void)
|
||||
sqlite3_close(connection);
|
||||
}
|
||||
|
||||
DECL void
|
||||
rope(void)
|
||||
{
|
||||
if (session)
|
||||
{ irc_destroy_session(session); }
|
||||
api_rope();
|
||||
}
|
||||
|
||||
DECL char *
|
||||
remind(char * who)
|
||||
{
|
||||
char * r;
|
||||
char * title;
|
||||
char * desc;
|
||||
char * repo;
|
||||
/* char * repo; */
|
||||
DBERR(sqlite3_reset(remind_stmt));
|
||||
DBERR(sqlite3_bind_text(remind_stmt, 1, who, -1, SQLITE_STATIC));
|
||||
const int i = sqlite3_step(remind_stmt);
|
||||
@ -69,19 +61,23 @@ remind(char * who)
|
||||
title = strdup(title);
|
||||
desc = (char *) sqlite3_column_text(remind_stmt, 1);
|
||||
if (desc) { desc = strdup(desc); } else { desc = ""; }
|
||||
repo = (char *) sqlite3_column_text(remind_stmt, 3);
|
||||
if (repo) { repo = strdup(repo); } else { repo = "<no link available>"; }
|
||||
/* repo = (char *) sqlite3_column_text(remind_stmt, 3); */
|
||||
/* if (repo) { repo = strdup(repo); } else { repo = "<no link available>"; } */
|
||||
/* if (-1 == asprintf(&r, */
|
||||
/* IRC_RED "%s: " IRC_YELLOW "%s" IRC_GREEN */
|
||||
/* " (@" IRC_BLUE "%s" IRC_GREEN ")" IRC_STOP, */
|
||||
/* title, desc, repo)) */
|
||||
if (-1 == asprintf(&r,
|
||||
IRC_RED "%s: " IRC_YELLOW "%s" IRC_GREEN
|
||||
" (@" IRC_BLUE "%s" IRC_GREEN ")" IRC_STOP,
|
||||
title, desc, repo))
|
||||
IRC_RED "%s: " IRC_YELLOW "%s" IRC_GREEN,
|
||||
title, desc))
|
||||
{ /* this will probably never happen. But it implies a memory failure */
|
||||
r = strdup(IRC_RED "No memory!" IRC_STOP); }
|
||||
r = strdup(IRC_RED "No memory!" IRC_STOP);
|
||||
}
|
||||
else
|
||||
{
|
||||
r = strdup(IRC_RED "No current assignment." IRC_STOP);
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -182,13 +178,11 @@ get_project_count_callback(void* data, int argc, char** argv, char** colname)
|
||||
}
|
||||
|
||||
DECL int
|
||||
get_project_count()
|
||||
get_project_count(void)
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
char const * sql = "SELECT COUNT(*) FROM project;";
|
||||
DBERR(sqlite3_exec(connection, sql, get_project_count_callback, &r, NULL));
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -204,7 +198,8 @@ get_nth_id(const int i)
|
||||
}
|
||||
|
||||
DECL void
|
||||
new_assignment(char const * const who, const int project)
|
||||
new_assignment(char const * const who,
|
||||
int const project)
|
||||
{
|
||||
DBERR(sqlite3_reset(new_assignment_stmt));
|
||||
DBERR(sqlite3_bind_text(new_assignment_stmt, 1, who, -1, SQLITE_STATIC));
|
||||
@ -233,9 +228,10 @@ purge_assignments(char const * const who)
|
||||
DECL int
|
||||
is_no_assignment(char const * const who)
|
||||
{
|
||||
const int e;
|
||||
DBERR(sqlite3_reset(is_no_assignment_stmt));
|
||||
DBERR(sqlite3_bind_text(is_no_assignment_stmt, 1, who, -1, SQLITE_STATIC));
|
||||
const int e = sqlite3_step(is_no_assignment_stmt);
|
||||
e = sqlite3_step(is_no_assignment_stmt);
|
||||
DBERR(e);
|
||||
return (e == SQLITE_DONE);
|
||||
}
|
||||
|
189
src/irc.c
189
src/irc.c
@ -1,18 +1,48 @@
|
||||
/* irc.c - IRC interface
|
||||
/* irc.c - IRC interface */
|
||||
|
||||
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.
|
||||
#define FULL_FREE(obj) \
|
||||
do \
|
||||
{ \
|
||||
if ((obj)) \
|
||||
{ \
|
||||
memset((obj), '\0', strlen((obj))); \
|
||||
free((obj)); \
|
||||
(obj) = NULL; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
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.
|
||||
#define PREFIX_COMMAND_CHAR '!'
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
version 3 along with Probotic.
|
||||
#define IRCMSG(msg) irc_cmd_msg(session, creds.channel, msg)
|
||||
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
char * username;
|
||||
char * password;
|
||||
char * channel;
|
||||
char * server;
|
||||
int port;
|
||||
} creds_t;
|
||||
|
||||
VARDECL creds_t creds =
|
||||
{
|
||||
.username = NULL,
|
||||
.password = NULL,
|
||||
.channel = NULL,
|
||||
.server = NULL, /* localhost? */
|
||||
#ifndef IRC_SSL_SUPPORT
|
||||
.port = 6667
|
||||
#else
|
||||
.port = 6669
|
||||
#endif /* !IRC_SSL_SUPPORT */
|
||||
};
|
||||
|
||||
VARDECL char * ident_password = NULL;
|
||||
|
||||
VARDECL irc_session_t * session;
|
||||
VARDECL irc_callbacks_t callbacks;
|
||||
|
||||
VARDECL char * current_username = NULL;
|
||||
|
||||
VARDECL char const * help_msg =
|
||||
/* IRC_GREEN "!help " IRC_STOP " : This message\n" */
|
||||
@ -24,15 +54,7 @@ IRC_GREEN "!reroll " IRC_STOP " : Rerolls assignment\n"
|
||||
IRC_GREEN "!request " IRC_STOP " : Request personal project\n"
|
||||
IRC_GREEN "!remind " IRC_STOP " : Prints your assignment\n";
|
||||
|
||||
#define PREFIX_COMMAND_CHAR '!'
|
||||
#define PREFIX_CHANNEL_COMMAND_CHAR '%'
|
||||
|
||||
VARDECL irc_session_t * session;
|
||||
VARDECL irc_callbacks_t callbacks;
|
||||
|
||||
VARDECL char * current_username = NULL;
|
||||
|
||||
#define IRCMSG(msg) irc_cmd_msg(session, creds.channel, msg)
|
||||
DECL void parse_command(char const * cmd);
|
||||
|
||||
DECL char *
|
||||
get_username(const char * origin)
|
||||
@ -127,15 +149,8 @@ event_channel(irc_session_t * lsession,
|
||||
(void) message;
|
||||
(void) count;
|
||||
/* parses the command */
|
||||
switch(*message)
|
||||
{
|
||||
case PREFIX_CHANNEL_COMMAND_CHAR:
|
||||
current_username = strdup(creds.channel);
|
||||
break;
|
||||
case PREFIX_COMMAND_CHAR:
|
||||
current_username = get_username(origin);
|
||||
break;
|
||||
}
|
||||
if (*message == PREFIX_COMMAND_CHAR)
|
||||
{ current_username = get_username(origin); }
|
||||
if (!current_username ||
|
||||
message[1] == '\0')
|
||||
{ return; }
|
||||
@ -144,44 +159,88 @@ event_channel(irc_session_t * lsession,
|
||||
current_username = NULL;
|
||||
}
|
||||
|
||||
DECL int
|
||||
init(void)
|
||||
{
|
||||
srand(time(NULL));
|
||||
if(api_init())
|
||||
{ ERR(DB_ERROR, "Error initializing database."); }
|
||||
memset(&callbacks, 0, sizeof(callbacks));
|
||||
callbacks.event_connect = event_connect;
|
||||
callbacks.event_channel = event_channel;
|
||||
session = irc_create_session(&callbacks);
|
||||
if (!session)
|
||||
{
|
||||
ERRMSG("Error creating IRC session");
|
||||
goto fail;
|
||||
}
|
||||
atexit(rope);
|
||||
assert(creds.username != NULL);
|
||||
assert(creds.server != NULL);
|
||||
if (irc_connect(session,
|
||||
creds.server, creds.port, creds.password,
|
||||
creds.username, creds.username, creds.username))
|
||||
{
|
||||
fprintf(stderr, "IRC ERROR: %s\n", irc_strerror(irc_errno(session)));
|
||||
exit(1);
|
||||
}
|
||||
FULL_FREE(creds.password);
|
||||
return 0;
|
||||
fail:
|
||||
FULL_FREE(creds.password);
|
||||
return 1;
|
||||
}
|
||||
/* 'abc' SINGLE
|
||||
'def ' SINGLE
|
||||
'ghi jkl' MULTI */
|
||||
|
||||
DECL int
|
||||
loop(void)
|
||||
has_arg(char const * cmd)
|
||||
{
|
||||
/* We should figure out how the failure happens so we can tell the user that. */
|
||||
if (irc_run(session) != 0)
|
||||
{ ERR(1, "Error running IRC session\nPossible issue: bad URL,"
|
||||
" no network connection, bad port, refused connection."); }
|
||||
while (isalnum(*cmd))
|
||||
{
|
||||
if (*cmd == '\0')
|
||||
{ break; }
|
||||
++cmd;
|
||||
}
|
||||
while (*cmd != '\0')
|
||||
{
|
||||
if (!isspace(*(++cmd)))
|
||||
{ return 1; }
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
DECL void
|
||||
parse_command(char const * cmd)
|
||||
{
|
||||
size_t i = 0;
|
||||
char* msgswp = NULL;
|
||||
/* size_t len = strlen(cmd); */
|
||||
|
||||
if ((i += has_arg(cmd)))
|
||||
{
|
||||
/* NO ARGUMENTS */
|
||||
if (strcmp(cmd, "remind") == 0)
|
||||
{
|
||||
msgswp = remind(current_username);
|
||||
ircmsg(creds.channel, "%s: %s", current_username, msgswp);
|
||||
}
|
||||
else if (strcmp(cmd, "help") == 0)
|
||||
{ ircmsg(creds.channel, help_msg); }
|
||||
else if (strcmp(cmd, "magic") == 0)
|
||||
{ ircmsg(creds.channel, "%s: " IRC_YELLOW "%d" IRC_STOP, current_username, (rand() % 100) + 1); }
|
||||
#ifndef NO_VULN_COMMANDS
|
||||
else if (strcmp(cmd, "dump") == 0)
|
||||
{
|
||||
ircmsg(creds.channel, "%s: All projects:", current_username);
|
||||
msgswp = dump();
|
||||
ircmsg(creds.channel, msgswp);
|
||||
}
|
||||
#endif /* !NO_VULN_COMMANDS */
|
||||
else if (strcmp(cmd, "reroll") == 0)
|
||||
{
|
||||
purge_assignments(current_username);
|
||||
random_assign(current_username);
|
||||
ircmsg(creds.channel, "%s: %s", current_username, remind(current_username));
|
||||
}
|
||||
}
|
||||
else /* HAS ARGUMENTS */
|
||||
{
|
||||
char const * const arg = cmd + i + 1;
|
||||
#ifndef NO_VULN_COMMANDS
|
||||
if (strncmp(cmd, "raw", i) == 0)
|
||||
{
|
||||
/* ircmsg(creds.channel, "%s: Executing SQL `%s'.", current_username, arg); */
|
||||
msgswp = raw(arg);
|
||||
ircmsg(creds.channel, msgswp);
|
||||
} else
|
||||
#endif /* !NO_VULN_COMMANDS */
|
||||
if (strncmp(cmd, "repo", i) == 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);
|
||||
}
|
||||
}
|
||||
free(msgswp);
|
||||
}
|
||||
|
||||
DECL void
|
||||
creds_free(void)
|
||||
{
|
||||
FULL_FREE(creds.username);
|
||||
FULL_FREE(creds.password);
|
||||
FULL_FREE(creds.channel);
|
||||
FULL_FREE(creds.server);
|
||||
}
|
||||
|
121
src/main.c
121
src/main.c
@ -1,21 +1,106 @@
|
||||
/* main.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.
|
||||
|
||||
*/
|
||||
/* main.c */
|
||||
|
||||
#define VERSION_STRING "1"
|
||||
|
||||
/* Parses the format username[:password]@server[:port] */
|
||||
|
||||
#define GENCOPY(dst,src,l) \
|
||||
do \
|
||||
{ \
|
||||
dst = malloc(sep + 1); \
|
||||
if (dst) \
|
||||
{ \
|
||||
strncpy(dst,src,l); \
|
||||
dst[len] = '\0'; \
|
||||
} \
|
||||
else \
|
||||
{ return 1; } \
|
||||
} while (0)
|
||||
|
||||
DECL int
|
||||
parse_url(char const * url)
|
||||
{
|
||||
size_t len = strlen(url);
|
||||
size_t sep = 0, ls = 0, rs;
|
||||
while (++sep < len && url[sep] != '@');
|
||||
while (++ls < len && url[ls] != ':')
|
||||
{
|
||||
if (ls >= sep)
|
||||
{ ls = 0; break; }
|
||||
}
|
||||
rs = sep;
|
||||
while (++rs < len && url[rs] != ':');
|
||||
if (rs == len)
|
||||
{ rs = 0; }
|
||||
GENCOPY(creds.username, url, ls ? ls : sep);
|
||||
if (ls)
|
||||
{
|
||||
GENCOPY(creds.password, url + ls + 1, sep - ls - 1);
|
||||
}
|
||||
if (rs)
|
||||
{
|
||||
GENCOPY(creds.server, url + sep + 1, rs - sep - 1);
|
||||
creds.port = atoi(url + rs + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
GENCOPY(creds.server, url + sep + 1, len - sep - 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#undef GENCOPY
|
||||
|
||||
DECL void
|
||||
rope(void)
|
||||
{
|
||||
if (session)
|
||||
{ irc_destroy_session(session); }
|
||||
api_rope();
|
||||
}
|
||||
|
||||
DECL int
|
||||
init(void)
|
||||
{
|
||||
srand(time(NULL));
|
||||
if(api_init())
|
||||
{ ERR(DB_ERROR, "Error initializing database."); }
|
||||
memset(&callbacks, 0, sizeof(callbacks));
|
||||
callbacks.event_connect = event_connect;
|
||||
callbacks.event_channel = event_channel;
|
||||
session = irc_create_session(&callbacks);
|
||||
if (!session)
|
||||
{
|
||||
ERRMSG("Error creating IRC session");
|
||||
goto fail;
|
||||
}
|
||||
atexit(rope);
|
||||
assert(creds.username != NULL);
|
||||
assert(creds.server != NULL);
|
||||
if (irc_connect(session,
|
||||
creds.server, creds.port, creds.password,
|
||||
creds.username, creds.username, creds.username))
|
||||
{
|
||||
fprintf(stderr, "IRC ERROR: %s\n", irc_strerror(irc_errno(session)));
|
||||
exit(1);
|
||||
}
|
||||
FULL_FREE(creds.password);
|
||||
return 0;
|
||||
fail:
|
||||
FULL_FREE(creds.password);
|
||||
return 1;
|
||||
}
|
||||
|
||||
DECL int
|
||||
loop(void)
|
||||
{
|
||||
/* We should figure out how the failure happens so we can tell the user that. */
|
||||
if (irc_run(session) != 0)
|
||||
{ ERR(1, "Error running IRC session\nPossible issue: bad URL,"
|
||||
" no network connection, bad port, refused connection."); }
|
||||
return 0;
|
||||
}
|
||||
|
||||
DECL void
|
||||
help(void)
|
||||
{
|
||||
@ -24,6 +109,8 @@ help(void)
|
||||
"-url URL - Sets the target URL\n"
|
||||
"-db DBFILE - Sets the database file (default: probotic_data.sqlite)\n"
|
||||
"-identify PASSWORD - Identifies against NickServ\n"
|
||||
"-version - Prints Version information\n"
|
||||
"-help - Prints this information\n"
|
||||
"\nUse format username[:password]@server[:port], port defaults to 6667.\n");
|
||||
}
|
||||
|
||||
@ -54,7 +141,7 @@ main (int argc,
|
||||
else if (strcmp(arg, "help") == 0)
|
||||
{ goto help; }
|
||||
if (argc < 2)
|
||||
{ goto nop; }
|
||||
{ goto help; }
|
||||
if (strcmp(arg, "db") == 0)
|
||||
{ db = argv[1]; }
|
||||
else if (strcmp(arg, "url") == 0)
|
||||
@ -70,7 +157,7 @@ main (int argc,
|
||||
++argv; --argc;
|
||||
}
|
||||
else
|
||||
{ nop: ERRFMT(1, "Oprand without option '%s'", arg); }
|
||||
{ goto help; }
|
||||
}
|
||||
}
|
||||
atexit(creds_free);
|
||||
|
223
src/parse.c
223
src/parse.c
@ -1,223 +0,0 @@
|
||||
/* 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
|
||||
|
||||
VARDECL creds_t creds =
|
||||
{
|
||||
.username = NULL,
|
||||
.password = NULL,
|
||||
.channel = NULL,
|
||||
.server = NULL, /* localhost? */
|
||||
#ifndef IRC_SSL_SUPPORT
|
||||
.port = 6667
|
||||
#else
|
||||
.port = 6669
|
||||
#endif /* IRC_SSL_SUPPORT */
|
||||
};
|
||||
|
||||
|
||||
|
||||
#if 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);
|
||||
}
|
||||
|
||||
#endif /* 0 */
|
||||
|
||||
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 */
|
||||
#ifndef NO_VULN_COMMANDS
|
||||
if (strcmp(cmd, "kill") == 0)
|
||||
{ exit(1); }
|
||||
#endif /* !NO_VULN_COMMANDS */
|
||||
if (strcmp(cmd, "remind") == 0)
|
||||
{
|
||||
msgswp = remind(current_username);
|
||||
ircmsg(creds.channel, "%s: %s", current_username, msgswp);
|
||||
}
|
||||
else if (strcmp(cmd, "help") == 0)
|
||||
{ ircmsg(creds.channel, help_msg); }
|
||||
else if (strcmp(cmd, "magic") == 0)
|
||||
{ ircmsg(creds.channel, "%s: " IRC_YELLOW "%d" IRC_STOP, current_username, (rand() % 100) + 1); }
|
||||
else if (strcmp(cmd, "dump") == 0)
|
||||
{
|
||||
#ifndef NO_VULN_COMMANDS
|
||||
ircmsg(creds.channel, "%s: All projects:", current_username);
|
||||
msgswp = dump();
|
||||
ircmsg(creds.channel, msgswp);
|
||||
#else
|
||||
ircmsg(creds.channel, "%s: dump disabled", current_username);
|
||||
#endif /* !NO_VULN_COMMANDS */
|
||||
}
|
||||
else if (strcmp(cmd, "reroll") == 0)
|
||||
{
|
||||
/* ircmsg(creds.channel, "%s: Rerolling...", current_username); */
|
||||
purge_assignments(current_username);
|
||||
random_assign(current_username);
|
||||
ircmsg(creds.channel, "%s: %s", current_username, remind(current_username));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* some arguments */
|
||||
char const * const arg = cmd + i + 1;
|
||||
if (strncmp(cmd, "raw", i) == 0)
|
||||
{
|
||||
#ifndef NO_VULN_COMMANDS
|
||||
/* ircmsg(creds.channel, "%s: Executing SQL `%s'.", current_username, arg); */
|
||||
msgswp = raw(arg);
|
||||
ircmsg(creds.channel, msgswp);
|
||||
#else
|
||||
ircmsg(creds.channel, "%s: raw disabled", current_username);
|
||||
#endif /* !NO_VULN_COMMANDS */
|
||||
}
|
||||
else if (strncmp(cmd, "repo", i) == 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);
|
||||
}
|
||||
}
|
||||
free(msgswp);
|
||||
}
|
||||
|
||||
/* Parses the format username[:password]@server[:port] */
|
||||
|
||||
#define GENCOPY(dst,src,l) \
|
||||
do \
|
||||
{ \
|
||||
dst = malloc(sep + 1); \
|
||||
if (dst) \
|
||||
{ \
|
||||
strncpy(dst,src,l); \
|
||||
dst[len] = '\0'; \
|
||||
} \
|
||||
else \
|
||||
{ return 1; } \
|
||||
} while (0)
|
||||
|
||||
DECL int
|
||||
parse_url(char const * url)
|
||||
{
|
||||
size_t len = strlen(url);
|
||||
size_t sep = 0, ls = 0, rs;
|
||||
while (++sep < len && url[sep] != '@');
|
||||
while (++ls < len && url[ls] != ':')
|
||||
{
|
||||
if (ls >= sep)
|
||||
{ ls = 0; break; }
|
||||
}
|
||||
rs = sep;
|
||||
while (++rs < len && url[rs] != ':');
|
||||
if (rs == len)
|
||||
{ rs = 0; }
|
||||
GENCOPY(creds.username, url, ls ? ls : sep);
|
||||
if (ls)
|
||||
{
|
||||
GENCOPY(creds.password, url + ls + 1, sep - ls - 1);
|
||||
}
|
||||
if (rs)
|
||||
{
|
||||
GENCOPY(creds.server, url + sep + 1, rs - sep - 1);
|
||||
creds.port = atoi(url + rs + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
GENCOPY(creds.server, url + sep + 1, len - sep - 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
DECL void
|
||||
creds_free(void)
|
||||
{
|
||||
FULL_FREE(creds.username);
|
||||
FULL_FREE(creds.password);
|
||||
FULL_FREE(creds.channel);
|
||||
FULL_FREE(creds.server);
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
/* stmt.c */
|
||||
|
||||
VARDECL sqlite3_stmt * remind_stmt;
|
||||
VARDECL char const remind_stmt_template[] =
|
||||
"SELECT "
|
13
src/unity.c
13
src/unity.c
@ -7,19 +7,16 @@
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <libircclient.h>
|
||||
#include <sqlite3.h>
|
||||
|
||||
#include "api.h"
|
||||
#include "error.h"
|
||||
#include "free.h"
|
||||
#include "help.h"
|
||||
#include "irc.h"
|
||||
#include "irccolors.h"
|
||||
#include "parse.h"
|
||||
#include "config.h"
|
||||
|
||||
#include "sql_stmt.c"
|
||||
#include "irc.c"
|
||||
#include "parse.c"
|
||||
#include "stmt.c"
|
||||
#include "api.c"
|
||||
#include "irc.c"
|
||||
#include "main.c"
|
||||
|
BIN
src/unity.o
BIN
src/unity.o
Binary file not shown.
@ -1,7 +1,2 @@
|
||||
#!/bin/sh
|
||||
# doubles as a cleanup script
|
||||
DIR=$(dirname $(readlink -f "$0"))
|
||||
cd $DIR
|
||||
TARGET=${TARGET-/opt/probotic}
|
||||
userdel probotic
|
||||
rm -rf $TARGET
|
||||
userdel -rf probotic
|
||||
|
Reference in New Issue
Block a user