Browse Source

Looks like I implemented .define but haven't committed yet.

Here you have it.
WIP-31-Mar-2021
Bubblegumdrop 3 years ago
parent
commit
38f191c997
15 changed files with 385 additions and 350 deletions
  1. +4
    -11
      data.h
  2. +127
    -124
      db.c
  3. +9
    -4
      db.h
  4. +111
    -37
      events.c
  5. +9
    -33
      events.h
  6. +6
    -0
      i18n.h
  7. +2
    -2
      io.c
  8. +1
    -1
      io.h
  9. +6
    -3
      levenshtein.c
  10. +1
    -1
      levenshtein.h
  11. +77
    -69
      main.c
  12. +11
    -5
      makefile
  13. +21
    -5
      signal.c
  14. +0
    -24
      strings.c
  15. +0
    -31
      strings.h

+ 4
- 11
data.h View File

@@ -1,6 +1,9 @@
#ifndef DATA_H
#define DATA_H

#include <sqlite3.h>
#include <libircclient.h>

/*
* We store data in IRC session context.
*/
@@ -9,6 +12,7 @@ struct irc_ctx_t {
char *channel;
char *nick;
char *server;
sqlite3 * db;
};

/*
@@ -21,15 +25,4 @@ struct spam_params_t {
float timer;
};

/*
* Eventually I'd like to be able to do insert_struct with filled out info or similar.
*/
struct quote_t {
int rowid;
const char *added_by;
const char *channel;
const char *subject;
const char *words;
};

#endif /* DATA_H */

+ 127
- 124
db.c View File

@@ -5,57 +5,46 @@
#include <sqlite3.h>
#include <stdio.h> /* size_t */
#include <stdlib.h> /* free */

#include "data.h"
#include "io.h"
#include "strings.h"
#include "i18n.h"
#include "unused.h"

static int print_col(sqlite3_stmt * pTableInfo, int col) {
int n, rc;
static int ct = 0;
char outfile[50];
size_t size;
printf("%s: ", sqlite3_column_name(pTableInfo, col));
switch (sqlite3_column_type(pTableInfo, col)) {
case SQLITE_INTEGER:
printf("%d ", sqlite3_column_int(pTableInfo, col));
break;
case SQLITE_FLOAT:
printf("%f ", sqlite3_column_double(pTableInfo, col));
break;
case SQLITE_TEXT:
printf("%s ", sqlite3_column_text(pTableInfo, col));
break;
case SQLITE_BLOB: //printf("%s",sqlite3_column_blob(pTableInfo, col));
/* fprintf(stderr, "IN BLOB bytes %d\n",
sqlite3_column_bytes(pTableInfo, col)); */
snprintf(outfile, 20, "outdata.%d.png", ct++);
n = sqlite3_column_bytes(pTableInfo, col);
if (n > 0)
size = (size_t)n;
else
break;
if ((rc = (int)file_write(outfile, sqlite3_column_blob(pTableInfo, col), size))) {
assert(rc == (int)size);
}
break;
case SQLITE_NULL:
printf("(null)\n");
break;
default:
printf(" *Cannot determine SQLITE TYPE* col=%d\n", col);
}
return 0;
}
static int run_script_callback(void *NotUsed, int argc, char **argv, char **azColName) {
#define FINISH_UP() \
rc = sqlite3_reset(stmt); \
if (SQLITE_OK != rc) { \
fprintf(stderr, string_errmsg_reset, sqlite3_errmsg(db)); \
} \
rc = sqlite3_clear_bindings(stmt); \
if (SQLITE_OK != rc) { \
fprintf(stderr, string_errmsg_clear, sqlite3_errmsg(db)); \
} \
return sqlite3_finalize(stmt)

static const char string_errmsg_bind[] = _("Error binding parameter: %s\n");
static const char string_errmsg_clear[] = _("Error clearing bindings: %s\n");
static const char string_errmsg_delete[] = _("Error deleting data: %s\n");
static const char string_errmsg_insert[] = _("Error inserting data: %s\n");
static const char string_errmsg_prepare[] = _("Error preparing data: %s\n");
static const char string_errmsg_readfile[] = _("Error reading file: %s\n");
static const char string_errmsg_reset[] = _("Error resetting statement: %s\n");
static const char string_errmsg_update[] = _("Error updating data: %s\n");
static const char string_null_msg[] = _("(null)\n");
static const char string_sqlite_version[] = _("SQLite version: %s\n");
static const char string_unmatched_comment[] = _("Unmatched comment: %d\n");

int run_script_callback(void *NotUsed, int argc, char **argv, char **azColName) {
int i;
UNUSED(NotUsed);
for (i = 0; i < argc; i++) {
printf(" => %s = %s\n", azColName[i], (argv[i] ? argv[i] : "NULL"));
printf(" => %s = %s\n", azColName[i], (argv[i] ? argv[i] : string_null_msg));
}
return 0;
return SQLITE_OK;
}
int run_script(sqlite3 * db, const char *script_filename) {
int j, rc;

int run_script(sqlite3 * db, int (*callback)(void *, int, char **, char **), const char *script_filename) {
int j, rc, incomment;
char *statements, *zErrMsg;
char *str1, *saveptr1, *token;
zErrMsg = 0;
@@ -63,123 +52,137 @@ int run_script(sqlite3 * db, const char *script_filename) {
fprintf(stderr, string_errmsg_readfile, script_filename);
return -1;
}
#if 0
rc = sqlite3_exec(db, statements, run_script_callback, 0, &zErrMsg);
if (SQLITE_OK != rc) {
fprintf(stderr, " !! SQL error: %s\n", sqlite3_errmsg(db));
sqlite3_free(zErrMsg);
}
#else
incomment = 0;
for (j = 1, str1 = statements;; j++, str1 = NULL) {
token = strtok_r(str1, "\n", &saveptr1);
if (token == NULL)
break;
if (strlen(token) > 2 && token[0] == '-' && token[1] == '-')
continue; /* Comment line; TODO multiline comment */
if (strstr(token, "/*")) {
incomment = 1;
}
if (strstr(token, "*/")) {
if (!incomment) {
fprintf(stderr, string_unmatched_comment, j);
}
incomment = 0;
}
if (incomment)
continue;
printf("%d: %s\n", j, token);
rc = sqlite3_exec(db, token, run_script_callback, 0, &zErrMsg);
rc = sqlite3_exec(db, token, callback, 0, &zErrMsg);
if (SQLITE_OK != rc) {
fprintf(stderr, " !! SQL error: %s\n", sqlite3_errmsg(db));
fprintf(stderr, "!! SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
break;
}
}
#endif
free(statements);
fprintf(stderr, "Bye!\n");
return SQLITE_OK;
}
int run_one(sqlite3 * db, const char *query) {
int i, n, rc;
sqlite3_stmt *stmt = NULL;
printf("> %s\n", query);
if (SQLITE_OK != (rc = sqlite3_prepare_v2(db, query, -1, &stmt, 0))) {
fprintf(stderr, string_errmsg_prepare, sqlite3_errmsg(db));
return SQLITE_ERROR;
}
while (SQLITE_ROW == (rc = sqlite3_step(stmt))) {
n = sqlite3_column_count(stmt);
for (i = 0; i < n; ++i) {
printf(" => ");
print_col(stmt, i);
puts("");
}
}
if (SQLITE_DONE != rc) {
fprintf(stderr, string_errmsg_update, sqlite3_errmsg(db));
}
if (SQLITE_OK != (rc = sqlite3_reset(stmt))) {
fprintf(stderr, string_errmsg_reset, sqlite3_errmsg(db));
}
if (SQLITE_OK != (rc = sqlite3_clear_bindings(stmt))) {
fprintf(stderr, string_errmsg_clear, sqlite3_errmsg(db));

int run_one(sqlite3 * db, int (*callback)(void *, int, char **, char **), const char *query) {
int rc = SQLITE_ERROR;
char *zErrMsg = NULL;
if (SQLITE_OK != (rc = sqlite3_exec(db, query, callback, 0, &zErrMsg))) {
fprintf(stderr, "!! SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
}
return sqlite3_finalize(stmt);
return rc;
}
int update_one(sqlite3 * db, int rowid, const char *param1, const char *param2) {
const char insert_stmt[] = "update quotedb set ? = ? where quote_id = ?";

int insert_new_definition(sqlite3 * db, const char *channel, const char *name, const char *word, const char *definition) {
const char insert_stmt[] = "insert into dictionarydb (date_added , channel , added_by, word , definition ) values (datetime('now'), ?, ?, ?, ?)";
int n, rc;
size_t maxlen;
sqlite3_stmt *stmt = NULL;
maxlen = 4096;
n = 0;
if (SQLITE_OK != (rc = sqlite3_prepare_v2(db, insert_stmt, -1, &stmt, 0))) {

rc = sqlite3_prepare_v2(db, insert_stmt, -1, &stmt, 0);
if (SQLITE_OK != rc) {
fprintf(stderr, string_errmsg_prepare, sqlite3_errmsg(db));
return SQLITE_ERROR;
goto _out;
}
#define S(x) if (SQLITE_OK != (rc = sqlite3_bind_text(stmt, ++n, x, (int)strnlen(x, maxlen), SQLITE_STATIC))) { \
fprintf(stderr, string_errmsg_bind, sqlite3_errmsg(db)); \
return SQLITE_ERROR; \
}
S(param1);
S(param2);

n = 0;
#define S(x) \
rc = sqlite3_bind_text(stmt, ++n, x, (int)strnlen(x, 4096), SQLITE_STATIC); \
if (SQLITE_OK != rc) { \
fprintf(stderr, string_errmsg_bind, sqlite3_errmsg(db)); \
goto _out; \
}
S(channel);
S(name);
S(word);
S(definition);
#undef S
sqlite3_bind_int(stmt, 3, rowid);
if (SQLITE_DONE != (rc = sqlite3_step(stmt))) {
fprintf(stderr, string_errmsg_update, sqlite3_errmsg(db));
}
if (SQLITE_OK != (rc = sqlite3_reset(stmt))) {
fprintf(stderr, string_errmsg_reset, sqlite3_errmsg(db));
fprintf(stderr, string_errmsg_insert, sqlite3_errmsg(db));
}
return sqlite3_finalize(stmt);
_out:
FINISH_UP();
}
int insert_row(sqlite3 * db, const char *channel, const char *added_by, const char *subject, const char *words) {
const char insert_stmt[] = "insert into quotedb (date_added, channel, added_by, subject, words) values (datetime('now'), ?, ?, ?, ?)";
int n, rc;
size_t maxlen;
int delete_from_table_by_rowid(sqlite3 * db, int rowid) {
int rc;
const char insert_stmt[] = "delete from dictionarydb where rowid = ?";
sqlite3_stmt *stmt = NULL;
maxlen = 4096;
n = 0;
if (SQLITE_OK != (rc = sqlite3_prepare_v2(db, insert_stmt, -1, &stmt, 0))) {
rc = sqlite3_prepare_v2(db, insert_stmt, -1, &stmt, 0);
if (SQLITE_OK != rc) {
fprintf(stderr, string_errmsg_prepare, sqlite3_errmsg(db));
return SQLITE_ERROR;
goto _out;
}
#define S(x) if (SQLITE_OK != (rc = sqlite3_bind_text(stmt, ++n, x, (int)strnlen(x, maxlen), SQLITE_STATIC))) { \
fprintf(stderr, string_errmsg_bind, sqlite3_errmsg(db)); \
return SQLITE_ERROR; \
}
S(channel);
S(added_by);
S(subject);
S(words);
#undef S
if (SQLITE_DONE != (rc = sqlite3_step(stmt))) {
fprintf(stderr, string_errmsg_insert, sqlite3_errmsg(db));

rc = sqlite3_bind_int(stmt, 1, rowid);
if (SQLITE_OK != rc) {
fprintf(stderr, string_errmsg_bind, sqlite3_errmsg(db));
goto _out;
}
if (SQLITE_OK != (rc = sqlite3_reset(stmt))) {
fprintf(stderr, string_errmsg_reset, sqlite3_errmsg(db));
if (SQLITE_DONE != (rc = sqlite3_step(stmt))) {
fprintf(stderr, string_errmsg_delete, sqlite3_errmsg(db));
}
return sqlite3_finalize(stmt);
_out:
FINISH_UP();
}

int sqlite_version(sqlite3 * db) {
int rc;
sqlite3_stmt *stmt = NULL;
if (SQLITE_OK != (rc = sqlite3_prepare_v2(db, "SELECT SQLITE_VERSION()", -1, &stmt, 0))) {
rc = sqlite3_prepare_v2(db, "SELECT SQLITE_VERSION()", -1, &stmt, 0);
if (SQLITE_OK != rc) {
fprintf(stderr, string_errmsg_prepare, sqlite3_errmsg(db));
return 1;
goto _out;
}
while (SQLITE_ROW == (rc = sqlite3_step(stmt))) {
printf(string_sqlite_version, sqlite3_column_text(stmt, 0));
}
if (SQLITE_DONE != rc) {
fprintf(stderr, string_errmsg_update, sqlite3_errmsg(db));
}
if (SQLITE_ROW == (rc = sqlite3_step(stmt))) {
printf("SQLite version: %s\n", sqlite3_column_text(stmt, 0));
_out:
FINISH_UP();
}

/*
* table_exists(tbl) =>
* 0 => table does not exist
* 1 => table exists
*/
int table_exists(sqlite3 * db, int (*callback)(void *, int, char **, char **), const char *table) {
int ret, rc;
char buf[BUFSIZ];
const char table_exists_query[] = "SELECT name FROM sqlite_master WHERE type = 'table' AND name = '%s'";
char *zErrMsg;

ret = 0;
memset(buf, 0, BUFSIZ);
sprintf(buf, table_exists_query, table);
rc = sqlite3_exec(db, buf, callback, 0, &zErrMsg);
if (SQLITE_OK == rc) {
ret = 1;
}
return sqlite3_finalize(stmt);

return ret;
}

+ 9
- 4
db.h View File

@@ -3,10 +3,15 @@

#include <sqlite3.h>

int insert_row(sqlite3 *, const char *, const char *, const char *, const char *);
int run_one(sqlite3 *, const char *);
int run_script(sqlite3 *, const char *);
typedef int (*callback)(void *, int, char **, char **);

int sqlite_version(sqlite3 *);
int update_one(sqlite3 *, int, const char *, const char *);
int run_one(sqlite3 *, callback, const char *);
int run_script_callback(void *, int argc, char **, char **);
int run_script(sqlite3 *, callback, const char *);

int insert_new_definition(sqlite3 *, const char *, const char *, const char *, const char *);
int delete_from_table_by_rowid(sqlite3 *, int);
int table_exists(sqlite3 *, callback, const char *);

#endif /* DB_H */

+ 111
- 37
events.c View File

@@ -1,17 +1,34 @@
#include <string.h>
#define _POSIX_C_SOURCE 200809L /* strnlen */
#include <string.h> /* strchr, strnlen */
#include <assert.h> /* assert */
#include <errno.h>
#include <errno.h> /* strerror */
#include <stdio.h> /* size_t */

#include "libircclient.h"
#include <libircclient.h>
#include <sqlite3.h>

#include "data.h"
#include "db.h"
#include "events.h"
#include "strings.h"
#include "i18n.h"
#include "threads.h"
#include "unused.h"

char F_SPAM_THREADS = STOPPED;
extern const char string_thread_failure[];
extern const char string_errmsg_reset[];
extern const char string_errmsg_prepare[];
extern const char string_errmsg_clear[];

static const char string_connect_success[] = _("Connected!\n Server: %s\n Port: %d\n Nick: %s\n Channel: %s\n");
static const char string_dcc_chat_closed[] = _("DCC %d: chat closed\n");
static const char string_dcc_chat_failure[] = _("DCC %d: error %s\n");
static const char string_dcc_chat_request[] = _("DCC chat [%d] requested from '%s' (%s)\n");
static const char string_dcc_chat_success[] = _("DCC %d: chat connected\n");
static const char string_dcc_send_file_failure[] = _("File sent error: %d\n");
static const char string_dcc_send_file_progress[] = _("File sent progress: %d\n");
static const char string_dcc_send_file_success[] = _("File sent successfully\n");
static const char string_dcc_send_request[] = _("DCC send [%d] requested from '%s' (%s): %s (%lu bytes)\n");
static const char string_spam_success[] = _("Spammer thread was started successfully.\n");

static char say_hi = 1;

@@ -21,6 +38,17 @@ static const char *admins[] = {

static int nadmins = 1;

static int IsAdmin(const char *name) {
int n, rc;
rc = 0;
for (n = 0; n < nadmins; n++) {
rc = !strcmp(name, admins[n]);
if (rc)
break;
}
return rc;
}

THREAD_FUNCTION(gen_spam) {
struct spam_params_t *sp = (struct spam_params_t *)arg;
while (RUNNING == F_SPAM_THREADS) {
@@ -32,8 +60,7 @@ THREAD_FUNCTION(gen_spam) {
return 0;
}

/* XXX this is a nasty shortcut to copy the signature of the other functions
* easily */
/* XXX this is a nasty shortcut to copy the signature of the other functions easily */
EVENT_GENERIC_SIGNATURE(start_spam) {
struct irc_ctx_t *ctx;
static struct spam_params_t spam1;
@@ -64,23 +91,23 @@ EVENT_GENERIC_SIGNATURE(start_spam) {
}

EVENT_GENERIC_SIGNATURE(dump_event) {
char buf[1024];
char buf[BUFSIZ];
unsigned int cnt;
size_t bufsize, nwritten;
size_t nwritten;

UNUSED(session);
bufsize = sizeof buf;

memset(buf, 0, bufsize);
memset(&buf, 0, BUFSIZ);
nwritten = 0;
cnt = 0;
while (cnt < count && nwritten < (bufsize-1)) {
do {
if (cnt)
nwritten += snprintf(buf + nwritten, 2, "|");
nwritten += snprintf(buf + nwritten, bufsize - nwritten - 1, "%s", params[cnt]);
nwritten += snprintf(buf + nwritten, BUFSIZ - nwritten - 1, "%s", params[cnt]);
cnt++;
}
buf[nwritten+1] = '\0';
while (cnt < count && nwritten < (BUFSIZ - 1));
buf[nwritten + 1] = '\0';

printf("[%s] %s : [%d] %s\n", event, origin ? origin : "(null)", cnt, buf);
}
@@ -111,20 +138,9 @@ EVENT_NUMERIC_SIGNATURE(irc_event_numeric) {
}
}

int IsAdmin(const char *name) {
int n, rc;
rc = 0;
for (n = 0; n < nadmins; n++) {
rc = !strcmp(name, admins[n]);
if (rc)
break;
}
return rc;
}

EVENT_GENERIC_SIGNATURE(irc_event_channel) {
struct irc_ctx_t *ctx;
char nickbuf[128];
char buf[BUFSIZ], nickbuf[128];

UNUSED(event);
UNUSED(params);
@@ -142,7 +158,6 @@ EVENT_GENERIC_SIGNATURE(irc_event_channel) {
}

ctx = (struct irc_ctx_t *)irc_get_ctx(session);
UNUSED(ctx);

if (!strcmp(params[1], ".stop")) {
irc_cmd_msg(session, params[0], ":x");
@@ -162,6 +177,66 @@ EVENT_GENERIC_SIGNATURE(irc_event_channel) {
irc_cmd_quit(session, "Bye!");
}

/* TODO sqlite3 .dump command */
if (!strcmp(params[1], ".dump")) {
}

/*
* .define phrase with words
* .define phrase with words => definition with words
* First form performs a SELECT
* Second form performs an INSERT
*/
if (params[1] == strstr(params[1], ".define")) {
char *firstword = NULL, *definition = NULL;

firstword = strchr(params[1], ' ');
definition = strstr(params[1], "=>");
if (NULL != firstword)
firstword++;
else
return;

if (NULL != definition) {
*(definition-1) = '\0';
definition += 3;
}
else
return;

printf("new define: %s => %s\n", firstword, definition);

if (NULL != firstword && *firstword && NULL != definition && *definition) {
if (SQLITE_OK == insert_new_definition(ctx->db, params[0], nickbuf, firstword, definition)) {
memset(buf, 0, sizeof buf);
snprintf(buf, (sizeof buf) - 1, "Definition for %s added.", firstword);
irc_cmd_msg(session, params[0], buf);
}
} else if (NULL != firstword && *firstword && NULL == definition) {
/* Lookup */
if (SQLITE_OK == insert_new_definition(ctx->db, params[0], nickbuf, firstword, definition)) {
memset(buf, 0, sizeof buf);
snprintf(buf, (sizeof buf) - 1, "Definition for %s added.", firstword);
irc_cmd_msg(session, params[0], buf);
}
}
}

if (params[1] == strstr(params[1], ".delete")) {
int n;
char *firstword = NULL;
firstword = strchr(params[1], ' ');
n = -1;
if (firstword) {
n = atoi(firstword);
}
if (n > 0 && SQLITE_OK == delete_from_table_by_rowid(ctx->db, n)) {
memset(buf, 0, sizeof buf);
snprintf(buf, (sizeof buf) - 1, "Deleted record %d.", n);
irc_cmd_msg(session, params[0], buf);
}
}

#if 0
if (ctx->insolents.find(nickbuf) == ctx->insolents.end())
ctx->insolents[nickbuf]
@@ -248,6 +323,7 @@ EVENT_GENERIC_SIGNATURE(irc_event_nick) {
#endif
}


DCC_RECV_SIGNATURE(dcc_recv_callback) {
static int count = 1;
char buf[12];
@@ -257,12 +333,12 @@ DCC_RECV_SIGNATURE(dcc_recv_callback) {

switch (status) {
case LIBIRC_ERR_CLOSED:
printf("DCC %d: chat closed\n", id);
printf(string_dcc_chat_closed, id);
break;

case 0:
if (!data) {
printf("DCC %d: chat connected\n", id);
printf(string_dcc_chat_success, id);
irc_dcc_msg(session, id, "Hehe");
} else {
printf("DCC %d: %s\n", id, data);
@@ -272,13 +348,13 @@ DCC_RECV_SIGNATURE(dcc_recv_callback) {
break;

default:
printf("DCC %d: error %s\n", id, irc_strerror(status));
printf(string_dcc_chat_failure, id, irc_strerror(status));
break;
}
}

EVENT_DCC_CHAT_SIGNATURE(irc_event_dcc_chat) {
printf("DCC chat [%d] requested from '%s' (%s)\n", dccid, nick, addr);
printf(string_dcc_chat_request, dccid, nick, addr);

irc_dcc_accept(session, dccid, 0, dcc_recv_callback);
}
@@ -287,25 +363,23 @@ DCC_RECV_SIGNATURE(dcc_file_recv_callback) {
UNUSED(session);
UNUSED(id);
if (status == 0 && length == 0) {
printf("File sent successfully\n");

printf("%s", string_dcc_send_file_success);
if (ctx)
fclose((FILE *) ctx);
} else if (status) {
printf("File sent error: %d\n", status);

printf(string_dcc_send_file_failure, status);
if (ctx)
fclose((FILE *) ctx);
} else {
if (ctx)
fwrite(data, 1, length, (FILE *) ctx);
printf("File sent progress: %d\n", length);
printf(string_dcc_send_file_progress, length);
}
}

EVENT_DCC_SEND_SIGNATURE(irc_event_dcc_send) {
FILE *fp;
printf("DCC send [%d] requested from '%s' (%s): %s (%lu bytes)\n", dccid, nick, addr, filename, size);
printf(string_dcc_send_request, dccid, nick, addr, filename, size);

if ((fp = fopen("file", "wb")) == 0)
abort();


+ 9
- 33
events.h View File

@@ -1,47 +1,23 @@
#ifndef EVENTS_H
#define EVENTS_H

#define DCC_RECV_SIGNATURE(event_name) \
void event_name (irc_session_t * session, irc_dcc_t id, int status, void * ctx, const char * data, unsigned int length)

#define EVENT_DCC_CHAT_SIGNATURE(event_name) \
void event_name \
(irc_session_t * session, \
const char * nick, \
const char * addr, \
irc_dcc_t dccid)
void event_name (irc_session_t * session, const char * nick, const char * addr, irc_dcc_t dccid)

#define EVENT_DCC_SEND_SIGNATURE(event_name) \
void event_name \
(irc_session_t * session, \
const char * nick, \
const char * addr, \
const char * filename, \
unsigned long size, \
irc_dcc_t dccid)
void event_name (irc_session_t * session, const char * nick, const char * addr, const char * filename, unsigned long size, irc_dcc_t dccid)

#define EVENT_GENERIC_SIGNATURE(event_name) \
void event_name \
(irc_session_t * session, \
const char *event, \
const char *origin, \
const char **params, \
unsigned int count)
void event_name (irc_session_t * session, const char *event, const char *origin, const char **params, unsigned int count)

#define EVENT_NUMERIC_SIGNATURE(event_name) \
void event_name \
(irc_session_t * session, \
unsigned int event, \
const char *origin, \
const char **params, \
unsigned int count)

#define DCC_RECV_SIGNATURE(event_name) \
void event_name \
(irc_session_t * session, \
irc_dcc_t id, \
int status, \
void * ctx, \
const char * data, \
unsigned int length)
void event_name (irc_session_t * session, unsigned int event, const char *origin, const char **params, unsigned int count)

DCC_RECV_SIGNATURE(dcc_file_recv_callback);
DCC_RECV_SIGNATURE(dcc_recv_callback);
EVENT_DCC_CHAT_SIGNATURE(irc_event_dcc_chat);
EVENT_DCC_SEND_SIGNATURE(irc_event_dcc_send);
EVENT_GENERIC_SIGNATURE(dump_event);


+ 6
- 0
i18n.h View File

@@ -0,0 +1,6 @@
#ifndef STRINGS_H
#define STRINGS_H

#define _(x) x

#endif /* STRINGS_H */

+ 2
- 2
io.c View File

@@ -59,7 +59,7 @@ size_t file_write(const char *fileName, const void *data, const size_t size) {
return numberBytesWritten;
}

int copy_file(const char *srcname, const char *dstname) {
size_t copy_file(const char *srcname, const char *dstname) {
int rc;
char *buf;
size_t nread, nwrite;
@@ -73,7 +73,7 @@ int copy_file(const char *srcname, const char *dstname) {
}
assert(nread == nwrite);
free(buf);
rc = 0;
rc = nread;
}
return rc;
}

+ 1
- 1
io.h View File

@@ -6,4 +6,4 @@
char *file_read(const char *filename, size_t *readSize);
size_t file_write(const char *fileName, const void *data, const size_t size);

#endif /* IO_H */
#endif /* IO_H */

+ 6
- 3
levenshtein.c View File

@@ -1,5 +1,5 @@
#define _POSIX_C_SOURCE 200809L /* strtok_r, strndup */
#include <string.h>
#define _POSIX_C_SOURCE 200809L /* strnlen */
#include <string.h> /* memset */
#include <stdlib.h> /* malloc */

#include "levenshtein.h"
@@ -35,7 +35,10 @@ int levenshtein(const char *s, const char *t) {
int i, j, n;
int ls = (int)strnlen(s, 128), lt = (int)strnlen(t, 128);
int *d;
d = (int*)malloc(sizeof(int) * (unsigned long)((ls + 1) * (lt + 1)));
size_t size;
size = sizeof(int) * (unsigned long)((ls + 1) * (lt + 1));
d = (int *)malloc(size);
memset(d, 0, size);
for (i = 0; i <= ls; i++)
for (j = 0; j <= lt; j++)
*(d + i * ls + j) = -1;


+ 1
- 1
levenshtein.h View File

@@ -3,4 +3,4 @@

int levenshtein(const char *s, const char *t);

#endif /* LEVENSHTEIN_H */
#endif /* LEVENSHTEIN_H */

+ 77
- 69
main.c View File

@@ -34,20 +34,20 @@
*
* 0. You just DO WHAT THE FUCK YOU WANT TO.
*/
#define _POSIX_C_SOURCE 200809L /* strtok_r, strndup */
#include <string.h>

#include <assert.h> /* assert */
#include <errno.h>
#include <errno.h> /* strerror */
#include <getopt.h> /* getopt */
#include <libircclient.h>
#include <stdio.h> /* size_t */
#include <string.h> /* memset */
#include <unistd.h> /* getopt */
#include "libircclient.h"

#include "data.h"
#include "db.h"
#include "events.h"
#include "levenshtein.h"
#include "strings.h"
#include "i18n.h"
#include "threads.h"
#include "unused.h"

@@ -55,9 +55,20 @@ extern void install_signal_handler(void);

char F_IRC_THREAD = STOPPED;
char F_MAIN_THREAD = STOPPED;
char F_SPAM_THREADS = STOPPED;

char IsIPv6Enabled = 0;
irc_session_t *irc_session = NULL;

const char string_usage_fmt[] =
_("Usage: %s [-46] [-q query] [-d sqlite db] [-h] [-p port] [-f script file] <[-s] server addr> [[-p] server port] <[-n] irc nick> <[-c] irc channel>\n");

const char string_connect_failure[] = _("Could not connect: %s\n");
const char string_ircthread_success[] = _("IRC thread was started successfully.\n");
const char string_opendb_failure[] = _("Can't open database: %s\n");
const char string_opendb_success[] = _("Open database successfully: %s\n");
const char string_thread_failure[] = _("CREATE_THREAD failed: %s\n");

THREAD_FUNCTION(IrcSessionThread) {
int rc;
const char *server;
@@ -82,12 +93,13 @@ THREAD_FUNCTION(IrcSessionThread) {
callbacks.event_numeric = irc_event_numeric;
callbacks.event_privmsg = irc_event_privmsg;

callbacks.event_channel_notice = dump_event;
callbacks.event_ctcp_action = dump_event;
callbacks.event_ctcp_rep = dump_event;
callbacks.event_ctcp_req = dump_event;
callbacks.event_invite = dump_event;
callbacks.event_kick = dump_event;
callbacks.event_mode = dump_event;
callbacks.event_nick = dump_event;
callbacks.event_notice = dump_event;
callbacks.event_part = dump_event;
callbacks.event_quit = dump_event;
@@ -100,6 +112,7 @@ THREAD_FUNCTION(IrcSessionThread) {
if (!irc_session) {
fprintf(stderr, string_connect_failure, irc_strerror(irc_errno(irc_session)));
F_IRC_THREAD = STOPPED;
goto _out;
}
irc_set_ctx(irc_session, ctx);
irc_option_set(irc_session, LIBIRC_OPTION_STRIPNICKS);
@@ -125,12 +138,14 @@ THREAD_FUNCTION(IrcSessionThread) {
if (rc) {
fprintf(stderr, string_connect_failure, irc_strerror(irc_errno(irc_session)));
F_IRC_THREAD = STOPPED;
goto _out;
}
/* and run into forever loop, generating events */
if (irc_run(irc_session)) {
fprintf(stderr, string_connect_failure, irc_strerror(irc_errno(irc_session)));
F_IRC_THREAD = STOPPED;
}
_out:
irc_destroy_session(irc_session);
irc_session = NULL;
}
@@ -141,37 +156,29 @@ THREAD_FUNCTION(IrcSessionThread) {
return NULL;
#endif
}

int main(int argc, char *argv[]) {
int c;
int rc;
int opt;
const char *db_name;
const char *query_str;
const char *filename;
sqlite3 *db;
int c, opt, rc;
const char *db_name, *filename, *query_str;
struct irc_ctx_t ctx;
thread_id_t tid;
#if 0
const char *s1 = "rosettacode";
const char *s2 = "raisethysword";
printf("distance between `%s' and `%s': %d\n", s1, s2, levenshtein(s1, s2));
#endif

install_signal_handler();
db_name = "familyGuy.sqlite3";
query_str = NULL;
filename = NULL;
rc = -1;
db = NULL;
memset(&ctx, 0, sizeof(struct irc_ctx_t));
ctx.port = 6667;

while ((opt = getopt(argc, argv, "c:d:f:hn:p:q:s:46")) != -1) {
switch (opt) {
case '4':
IsIPv6Enabled = 0;
break;
case '6':
IsIPv6Enabled = 1;
break;
case '4':
IsIPv6Enabled = 0;
break;
case '6':
IsIPv6Enabled = 1;
break;
case 'c':
ctx.channel = optarg;
break;
@@ -200,57 +207,58 @@ int main(int argc, char *argv[]) {
break;
}
}
if (NULL != db_name) {
if (SQLITE_OK == (rc = sqlite3_open(db_name, &db))) {
printf("%s", string_opendb_success);
sqlite_version(db);
}
} else {
fprintf(stderr, string_opendb_failure, sqlite3_errmsg(db));

rc = sqlite3_open(db_name, &ctx.db);
if (rc != SQLITE_OK) {
fprintf(stderr, string_opendb_failure, sqlite3_errmsg(ctx.db));
return -1;
}
} else {
printf(string_opendb_success, db_name);
sqlite_version(ctx.db);

/*run_one(db, create_db_query);*/
printf("%d\n", table_exists(ctx.db, run_script_callback, "dictionarydb"));

if (NULL != query_str) {
rc = run_one(db, query_str);
} else if (NULL != filename) {
rc = run_script(db, filename);
} else if (argc == 4) {
if (argc > 1)
ctx.server = argv[1];
if (argc > 2)
ctx.nick = argv[2];
if (argc > 3)
ctx.channel = argv[3];
if (!ctx.server || !ctx.nick || !ctx.channel) {
if (NULL != query_str) {
rc = run_one(ctx.db, run_script_callback, query_str);
} else if (NULL != filename) {
rc = run_script(ctx.db, run_script_callback, filename);
} else if (optind < argc) {
ctx.server = argv[optind++];
if (optind < argc)
ctx.nick = argv[optind++];
if (optind < argc)
ctx.channel = argv[optind++];
if (!ctx.server || !ctx.nick || !ctx.channel) {
fprintf(stderr, string_usage_fmt, argv[0]);
return -1;
}
F_IRC_THREAD = RUNNING;
F_MAIN_THREAD = RUNNING;
if (CREATE_THREAD(&tid, IrcSessionThread, &ctx)) {
printf(string_thread_failure, strerror(errno));
} else {
printf("%s", string_ircthread_success);
}
while (RUNNING == F_MAIN_THREAD) {
sleep(1);
/* TODO separare thread to monitor input, I'd also like to be
* able to restart / reconnect, I think that may happen in here */
c = getchar();
if ('q' == c) {
if (irc_session)
irc_cmd_quit(irc_session, "Bye!");
F_MAIN_THREAD = STOPPED;
}
}
F_IRC_THREAD = STOPPED;
F_SPAM_THREADS = STOPPED;
rc = 0;
} else {
fprintf(stderr, string_usage_fmt, argv[0]);
return -1;
}
F_IRC_THREAD = RUNNING;
F_MAIN_THREAD = RUNNING;
if (CREATE_THREAD(&tid, IrcSessionThread, &ctx)) {
printf(string_thread_failure, strerror(errno));
} else {
printf("%s", string_ircthread_success);
}
while (RUNNING == F_MAIN_THREAD) {
sleep(1);
c = getchar();
if ('q' == c) {
if (irc_session)
irc_cmd_quit(irc_session, "Bye!");
F_MAIN_THREAD = STOPPED;
}
}
F_IRC_THREAD = STOPPED;
F_SPAM_THREADS = STOPPED;
rc = 0;
} else {
fprintf(stderr, string_usage_fmt, argv[0]);
return -1;
}

sqlite3_close(db);
sqlite3_close(ctx.db);
return rc;
}

+ 11
- 5
makefile View File

@@ -16,17 +16,23 @@ OPT := -ggdb -O0

ifeq ($(O),1)
OPT := -g -O1
else ifeq ($(O),2)
OPT := -g0 -O2
else ifeq ($(O),s)
OPT := -g0 -Os
endif

ifeq ($(O),2)
OPT := -g0 -O2
ifeq ($(LTO),1)
LDFLAGS += -funroll-loops -flto -fwhole-program
endif

ifeq ($(O),s)
OPT := -g0 -Os
ifeq ($(PROF),1)
DEBUG += --coverage -pg
LDFLAGS += -lgcov
endif

FLAGS := -D_FORTIFY_SOURCE=2 -fasynchronous-unwind-tables -fexceptions -fpie -Wl,-pie -fpic -fstack-clash-protection -fstack-protector-all -fstack-protector-strong -g -grecord-gcc-switches -fcf-protection -pipe -Wformat -Werror=format-security -Werror=implicit-function-declaration -Wl,-z,defs -Wl,-z,now -Wl,-z,relro
F := -Wl,-z,defs -Wl,-z,now -Wl,-z,relro -fpie -Wl,-pie -fpic -fstack-clash-protection -fstack-protector-all -fstack-protector-strong
FLAGS := -D_FORTIFY_SOURCE=2 -fasynchronous-unwind-tables -fexceptions -g -grecord-gcc-switches -fcf-protection -pipe -Wformat -Werror=format-security -Werror=implicit-function-declaration
CFLAGS += $(FLAGS)
LDFLAGS += $(FLAGS)



+ 21
- 5
signal.c View File

@@ -1,12 +1,24 @@
#include <signal.h> /* signal */
#include <stdio.h> /* fprintf */
#include <string.h> /* memset */
#include "libircclient.h"

#include <libircclient.h>

#include "threads.h" /* F_* */
#include "strings.h"
#include "i18n.h"

#ifdef BUFSIZ
#undef BUFSIZ
#endif
#define BUFSIZ 127

extern irc_session_t *irc_session;

static const char string_signal_recv_fmt[] = _("Received %s, exiting.\n");
static const char string_signal_unknown_fmt[] = _("(Unknown Signal)");

static void SignalHandler(int sig) {
char buf[512];
char buf[BUFSIZ+1];
const char *s = string_signal_unknown_fmt;
#define CASE(x) case x: s = #x; break
switch (sig) {
@@ -21,16 +33,20 @@ static void SignalHandler(int sig) {
break;
}
#undef CASE
memset(&buf, 0, sizeof buf);
snprintf(buf, (sizeof buf) - 1, string_signal_fmt, s);

memset(&buf, 0, BUFSIZ+1);
snprintf(buf, BUFSIZ, string_signal_recv_fmt, s);
fprintf(stderr, "%s", buf);

F_IRC_THREAD = STOPPED;
F_MAIN_THREAD = STOPPED;
F_SPAM_THREADS = STOPPED;

if (NULL != irc_session)
irc_cmd_quit(irc_session, buf);
/* TODO: clean exit */
}

void install_signal_handler(void) {
signal(SIGTERM, SignalHandler);
signal(SIGINT, SignalHandler);


+ 0
- 24
strings.c View File

@@ -1,24 +0,0 @@
#include "strings.h"

const char string_connect_failure[] = "Could not connect: %s\n";
const char string_connect_success[] = "Connected!\n Server: %s\n Port: %d\n Nick: %s\n Channel: %s\n";

const char string_errmsg_bind[] = "Error binding parameter: %s\n";
const char string_errmsg_clear[] = "Error clearing bindings: %s\n";
const char string_errmsg_insert[] = "Error inserting data: %s\n";
const char string_errmsg_prepare[] = "Error preparing data: %s\n";
const char string_errmsg_readfile[] = "Error reading file: %s\n";
const char string_errmsg_reset[] = "Error resetting statement: %s\n";
const char string_errmsg_update[] = "Error updating data: %s\n";

const char string_opendb_failure[] = "Can't open database: %s\n";
const char string_opendb_success[] = "Open database successfully\n";

const char string_signal_fmt[] = "Received %s, exiting.\n";
const char string_signal_unknown_fmt[] = "(Unknown Signal)";

const char string_usage_fmt[] = "Usage: %s [-46] [-q query] [-d sqlite db] [-h] [-p port] [-f script file] <[-s] server addr> [[-p] server port] <[-n] irc name> <[-c] irc channel>\n";

const char string_spam_success[] = "Spammer thread was started successfully.\n";
const char string_ircthread_success[] = "IRC thread was started successfully.\n";
const char string_thread_failure[] = "CREATE_THREAD failed: %s\n";

+ 0
- 31
strings.h View File

@@ -1,31 +0,0 @@
#ifndef STRINGS_H
#define STRINGS_H

extern const char string_connect_failure[];
extern const char string_connect_success[];

extern const char string_errmsg_bind[];
extern const char string_errmsg_clear[];
extern const char string_errmsg_insert[];
extern const char string_errmsg_prepare[];
extern const char string_errmsg_readfile[];
extern const char string_errmsg_reset[];
extern const char string_errmsg_update[];

extern const char string_opendb_failure[];
extern const char string_opendb_success[];

extern const char string_signal_fmt[];
extern const char string_signal_unknown_fmt[];

extern const char string_usage_fmt[];

/* Threads */
extern const char string_spam_success[];

extern const char string_ircthread_success[];

/* Generic thread failure */
extern const char string_thread_failure[];

#endif /* STRINGS_H */

Loading…
Cancel
Save