diff --git a/Makefile b/Makefile index ba19d8e..fd28ff8 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,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 @@ -31,17 +33,20 @@ 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} @@ -51,4 +56,4 @@ help: @echo " submodules" @echo " clean" -.PHONY: submodules clean help +.PHONY: all submodules clean help diff --git a/build.sh b/build.sh deleted file mode 100755 index f699171..0000000 --- a/build.sh +++ /dev/null @@ -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: $?" diff --git a/include/api.h b/include/api.h deleted file mode 100644 index 12edea0..0000000 --- a/include/api.h +++ /dev/null @@ -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 diff --git a/include/config.mk.h b/include/config.mk.h new file mode 100644 index 0000000..ccfc09d --- /dev/null +++ b/include/config.mk.h @@ -0,0 +1 @@ +#define DBFILE "probotic_data.sqlite" diff --git a/include/error.h b/include/error.h index be2e428..d5d7783 100644 --- a/include/error.h +++ b/include/error.h @@ -1,7 +1,3 @@ -#ifndef ERROR_H_ - -#include - #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 diff --git a/include/free.h b/include/free.h deleted file mode 100644 index dba7441..0000000 --- a/include/free.h +++ /dev/null @@ -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 diff --git a/include/help.h b/include/help.h deleted file mode 100644 index c62d093..0000000 --- a/include/help.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef HELP_H_ - -VARDECL char const * help_msg; - -#define HELP_H_ -#endif diff --git a/include/irc.h b/include/irc.h deleted file mode 100644 index 7175220..0000000 --- a/include/irc.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef IRC_H_ - -#include - -#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 diff --git a/include/irccolors.h b/include/irccolors.h index f446a92..f72432b 100644 --- a/include/irccolors.h +++ b/include/irccolors.h @@ -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 diff --git a/include/parse.h b/include/parse.h deleted file mode 100644 index a5b3ba5..0000000 --- a/include/parse.h +++ /dev/null @@ -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 diff --git a/install.sh b/install.sh index 4cee13c..652c937 100644 --- a/install.sh +++ b/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 diff --git a/src/api.c b/src/api.c index 1ac539d..5ecfa7d 100644 --- a/src/api.c +++ b/src/api.c @@ -1,6 +1,6 @@ -#define DBFILE "probotic_data.sqlite" +/* api.c - Database API */ -#define stmt_prepare(stmt) \ +#define stmt_prepare(stmt) \ sqlite3_prepare_v2(connection, stmt ## _template, -1, &stmt, NULL) VARDECL char const * db = DBFILE; @@ -9,25 +9,25 @@ VARDECL sqlite3 * connection = NULL; DECL void DBERR(const int l) { - if(l != SQLITE_OK && l != SQLITE_ROW && l != SQLITE_DONE) - { - fprintf(stderr, - "sqlite (%d): %s\n", - sqlite3_errcode(connection), sqlite3_errmsg(connection)); - exit(DB_ERROR); - } + if(l != SQLITE_OK && l != SQLITE_ROW && l != SQLITE_DONE) + { + fprintf(stderr, + "sqlite (%d): %s\n", + sqlite3_errcode(connection), sqlite3_errmsg(connection)); + exit(DB_ERROR); + } } 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)); - DBERR(stmt_prepare(new_assignment_stmt)); - DBERR(stmt_prepare(purge_assignments_stmt)); + DBERR(stmt_prepare(new_assignment_stmt)); + DBERR(stmt_prepare(purge_assignments_stmt)); DBERR(stmt_prepare(is_no_assignment_stmt)); return 0; } @@ -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,20 +61,24 @@ 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 = ""; } - if (-1 == asprintf(&r, - IRC_RED "%s: " IRC_YELLOW "%s" IRC_GREEN - " (@" IRC_BLUE "%s" IRC_GREEN ")" IRC_STOP, - title, desc, repo)) + /* repo = (char *) sqlite3_column_text(remind_stmt, 3); */ + /* if (repo) { repo = strdup(repo); } else { repo = ""; } */ + /* 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, + title, desc)) { /* this will probably never happen. But it implies a memory failure */ - r = strdup(IRC_RED "No memory!" IRC_STOP); } - } - else - { - r = strdup(IRC_RED "No current assignment." IRC_STOP); - } - return r; + r = strdup(IRC_RED "No memory!" IRC_STOP); + } + else + { + r = strdup(IRC_RED "No current assignment." IRC_STOP); + } + } + return r; } DECL void @@ -129,14 +125,14 @@ rtos(void * data, *r = (char *)calloc(data_len, sizeof(char)); for(int i = 0; i < argc; i++){ - strcat(*r, "|"); - if(argv[i]){ - strcat(*r, argv[i]); - } - else - { - strcat(*r, "NULL"); - } + strcat(*r, "|"); + if(argv[i]){ + strcat(*r, argv[i]); + } + else + { + strcat(*r, "NULL"); + } } strcat(*r, "|\n"); @@ -164,7 +160,7 @@ raw(char const * const sql) if (errmsg){ free(r); - r = errmsg; + r = errmsg; } else { strcat(r, "\00"); } return r; } @@ -176,40 +172,39 @@ get_project_count_callback(void* data, int argc, char** argv, char** colname) { (void)argc; (void)colname; - int* count = (int*)data; - *count = atoi(argv[0]); - return 0; + int* count = (int*)data; + *count = atoi(argv[0]); + return 0; } 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; + int r = 0; + char const * sql = "SELECT COUNT(*) FROM project;"; + DBERR(sqlite3_exec(connection, sql, get_project_count_callback, &r, NULL)); + return r; } DECL int get_nth_id(const int i) { - int r; - DBERR(sqlite3_reset(get_nth_id_stmt)); - DBERR(sqlite3_bind_int(get_nth_id_stmt, 1, i)); - DBERR(sqlite3_step(get_nth_id_stmt)); - r = sqlite3_column_int(get_nth_id_stmt, 0); - return r; + int r; + DBERR(sqlite3_reset(get_nth_id_stmt)); + DBERR(sqlite3_bind_int(get_nth_id_stmt, 1, i)); + DBERR(sqlite3_step(get_nth_id_stmt)); + r = sqlite3_column_int(get_nth_id_stmt, 0); + return r; } 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)); - DBERR(sqlite3_bind_int(new_assignment_stmt, 2, project)); - DBERR(sqlite3_step(new_assignment_stmt)); + DBERR(sqlite3_reset(new_assignment_stmt)); + DBERR(sqlite3_bind_text(new_assignment_stmt, 1, who, -1, SQLITE_STATIC)); + DBERR(sqlite3_bind_int(new_assignment_stmt, 2, project)); + DBERR(sqlite3_step(new_assignment_stmt)); } DECL void @@ -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); } diff --git a/src/irc.c b/src/irc.c index 42e8362..537b5e6 100644 --- a/src/irc.c +++ b/src/irc.c @@ -1,18 +1,48 @@ -/* irc.c - IRC interface +/* irc.c - IRC interface */ + +#define FULL_FREE(obj) \ + do \ + { \ + if ((obj)) \ + { \ + memset((obj), '\0', strlen((obj))); \ + free((obj)); \ + (obj) = NULL; \ + } \ + } while (0) - 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 PREFIX_COMMAND_CHAR '!' - 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 IRCMSG(msg) irc_cmd_msg(session, creds.channel, msg) - You should have received a copy of the GNU General Public License - version 3 along with Probotic. +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; } +/* 'abc' SINGLE + 'def ' SINGLE + 'ghi jkl' MULTI */ + DECL int -init(void) +has_arg(char const * cmd) { - 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) + while (isalnum(*cmd)) { - ERRMSG("Error creating IRC session"); - goto fail; + if (*cmd == '\0') + { break; } + ++cmd; } - 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)) + while (*cmd != '\0') { - fprintf(stderr, "IRC ERROR: %s\n", irc_strerror(irc_errno(session))); - exit(1); + if (!isspace(*(++cmd))) + { return 1; } } - FULL_FREE(creds.password); return 0; -fail: - FULL_FREE(creds.password); - return 1; } -DECL int -loop(void) +DECL void +parse_command(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."); } - return 0; + 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); } diff --git a/src/main.c b/src/main.c index 4c6f44e..5c7f870 100644 --- a/src/main.c +++ b/src/main.c @@ -1,20 +1,105 @@ -/* main.c +/* 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. +#define VERSION_STRING "1" + +/* Parses the format username[:password]@server[:port] */ - 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 GENCOPY(dst,src,l) \ + do \ + { \ + dst = malloc(sep + 1); \ + if (dst) \ + { \ + strncpy(dst,src,l); \ + dst[len] = '\0'; \ + } \ + else \ + { return 1; } \ + } while (0) - You should have received a copy of the GNU General Public License - version 3 along with Probotic. +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 -#define VERSION_STRING "1" +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); diff --git a/src/parse.c b/src/parse.c deleted file mode 100644 index dcb9816..0000000 --- a/src/parse.c +++ /dev/null @@ -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); -} diff --git a/src/sql_stmt.c b/src/stmt.c similarity index 98% rename from src/sql_stmt.c rename to src/stmt.c index fa4a293..899b205 100644 --- a/src/sql_stmt.c +++ b/src/stmt.c @@ -1,3 +1,5 @@ +/* stmt.c */ + VARDECL sqlite3_stmt * remind_stmt; VARDECL char const remind_stmt_template[] = "SELECT " diff --git a/src/unity.c b/src/unity.c index 048d8fe..5fc0490 100644 --- a/src/unity.c +++ b/src/unity.c @@ -7,19 +7,16 @@ #include #include #include +#include +#include #include -#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" diff --git a/src/unity.o b/src/unity.o deleted file mode 100644 index 884780a..0000000 Binary files a/src/unity.o and /dev/null differ diff --git a/uninstall.sh b/uninstall.sh index ac13841..abf88f0 100644 --- a/uninstall.sh +++ b/uninstall.sh @@ -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