SUBDIRS = lib src doc
prepare:
$(MAKE) -C src $@
-all: prepare
+%: prepare
.PHONY: prepare
# gnulib modules used by this package.
gnulib_name=libgnu
-gnulib_modules="list xlist xstrndup"
+gnulib_modules="xoset rbtree-oset"
# Additional xgettext options to use. Use "\\\newline" to break lines.
XGETTEXT_OPTIONS=$XGETTEXT_OPTIONS'\\\
# Checks for programs.
AC_PROG_CC_C99
AC_CHECK_PROGS([AUTOGEN], [autogen],
- [AC_MSG_ERROR([GNU Autogen required, but not found])])
+ [AC_MSG_WARN([GNU Autogen required for developer build])])
gl_EARLY
gl_INIT
AC_GNU_SOURCE
[AC_MSG_ERROR([libircclient header not found])])
AC_CHECK_LIB([ircclient],[irc_create_session],[],
[AC_MSG_ERROR([libircclient library not found])])
-AC_CHECK_HEADER([dbi/dbi.h],[],
+AC_CHECK_HEADER([mysql/mysql.h],[],
[AC_MSG_ERROR([Libdbi headers not found])])
-AC_CHECK_LIB([dbi],[dbi_conn_new],[],
+AC_CHECK_LIB([mysqlclient],[mysql_real_connect],[],
[AC_MSG_ERROR([Libdbi library not found])])
# Checks for typedefs, structures, and compiler characteristics.
-AM_CFLAGS = -I$(top_srcdir)/lib
-.DEFAULT_GOAL = maintainer_all
+AM_CPPFLAGS = -I$(top_srcdir)/lib
+AM_CFLAGS= -Wno-unused-parameter
bin_PROGRAMS = thales
thales_SOURCES = main.c cmd.h cmd.c \
- error.h irc.h irc.c defaults.c defaults.h \
- sentry.h sentry.c init_query.h init_query.c \
- function_query.h function_query.c query.h query.c
+ error.h irc.h irc.c writer.c writer.h
thales_LDADD = $(top_builddir)/lib/libgnu.a
%.c %.h: %.def %.tpl
cd $(srcdir) && $(AUTOGEN) $<
-prepare: init_query.c query.c
-check-syntax:
+prepare:
+check-syntax: prepare
$(COMPILE) -o /dev/null -S ${CHK_SOURCES}
-
-.PHONY: prepare
+GTAGS: prepare
+ gtags -I .
+.PHONY: prepare GTAGS check-syntax
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
-#include <envz.h>
-#include "utility.h"
+#include "error.h"
+
+static const char *default_server = "irc.freenode.net";
+static const unsigned short default_port = 6667;
+static const char *default_nickname ="__GNU_Thales__";
static void
printf_option (const char *option, const char *description)
printf_option ("--help, -h", "Display this information");
printf_option ("--version, -v", "Display thales version");
printf_option ("--debug, -d", "Enable output of debug information");
- printf_option ("--config, -C", "Override default configuration file");
+ printf_option ("--config, -C", "Override default work_options file");
printf_option ("--server, -s", "Irc server to connect");
printf_option ("--port, -p", "Port to connect");
printf_option ("--nick, -n", "Nickname to login with");
"or FITNESS FOR A PARTICULAR PURPOSE.");
}
+static void
+cmd_set_defaults (struct work_options *opts)
+{
+ opts->nickname = opts->nickname ? opts->nickname : default_nickname;
+ opts->server = opts->server ? opts->server : default_server;
+ opts->port = opts->port ? opts->port : default_port;
+}
+
void
-parse_cmd_options (struct irc_options *opts, struct config_options *config_opts,
- int argc, char **argv)
+parse_cmd_options (struct work_options *opts, int argc, char **argv)
{
- const char *optstr = "hdvs:p:C:n:";
+ const char *optstr = "hvs:p:C:n:";
const struct option longopts[] = {
{"help", no_argument, NULL, 'h'},
{"server", required_argument, NULL, 's'},
{"port", required_argument, NULL, 'p'},
- {"debug", no_argument, NULL, 'd'},
{"version", no_argument, NULL, 'v'},
{"nick", required_argument, NULL, 'n'},
- {"config", required_argument, NULL, 'C'},
+ {NULL, 0, NULL, 0}
};
int val;
while ((val = getopt_long (argc, argv, optstr, longopts, NULL)) != EOF)
case 'h':
print_help ();
exit (EXIT_SUCCESS);
+ break;
case 'v':
print_version ();
exit (EXIT_SUCCESS);
- case 'C':
- config_opts->conf_filename = optarg;
break;
case 's':
opts->server = optarg;
break;
case 'p':
- opts->port = (unsigned short int) atoi (optarg); // Port in two byte integral.
+ opts->port = (unsigned short int) atoi (optarg); // Port in two byte integral.
break;
case 'n':
- opts->nick = optarg;
+ opts->nickname = optarg;
break;
- case 'd':
- config_opts->debug = true;
case '?':
+ default:
+ print_help ();
exit (EXIT_FAILURE);
}
+ cmd_set_defaults (opts);
opts->channels = argv + optind;
-}
-
-
-FILE*
-default_config_file(void)
-{
- /* Have to replace hardcoded pathes to
- Automake generated */
- const char *filenames[] ={
- getenv("THALES_CONFIG"),
- "~/.thales",
- "/etc/thales"
- };
- FILE *config_file;
-
- for (int index = 0; index != countof(filenames); ++index)
- if (filenames[index] && (config_file = fopen(filenames[index], "r")))
- return config_file;
- return NULL;
-}
-
-static inline void
-fill_envz(char **envz, size_t *envz_len, FILE *stream)
-{
- char *line = NULL;
- size_t line_len;
-
- while (getline(&line, &line_len, stream) > 0)
- argz_add(envz, envz_len, line);
- free(line);
-}
-
-void
-parse_mysql_options(struct mysql_options *opts, FILE *stream)
-{
- char *envz = NULL;
- size_t envz_len = 0;
-
- fill_envz(&envz, &envz_len, stream);
-
- opts->database = xstrdup_safe(envz_get(envz, envz_len, "database"));
- opts->host = xstrdup_safe(envz_get(envz, envz_len, "host"));
- opts->password = xstrdup_safe(envz_get(envz, envz_len, "password"));
- opts->port = xstrdup_safe(envz_get(envz, envz_len, "port"));
- opts->username = xstrdup_safe(envz_get(envz, envz_len, "username"));
+ if (!*opts->channels)
+ { /* No channels specified */
+ print_help ();
+ exit (EXIT_FAILURE);
+ }
}
#include <stdbool.h>
#include <stdio.h>
-struct irc_options {
+struct work_options
+{
const char *server;
- const char *nick;
+ const char *nickname;
unsigned short port;
char **channels;
};
-struct mysql_options {
- const char *host;
- const char *username;
- const char *password;
- const char *database;
- unsigned short int port;
-};
-
-struct config_options {
- bool debug;
- const char *conf_filename;
-};
-FILE* default_config_file(void);
-void parse_cmd_options(struct irc_options *irc_opts, struct config_options *config_opts,
- int argc, char **argv);
-void parse_mysql_options(struct mysql_options *opts, FILE *stream);
+FILE *default_config_file (void);
+void parse_cmd_options (struct work_options *opts, int argc, char **argv);
#endif
+++ /dev/null
-#include "defaults.h"
-
-const char *default_server = "irc.freenode.net";
-const unsigned short default_port = 6667;
-const char *default_nick="thales";
+++ /dev/null
-#ifndef DEFAULTS_H
-#define DEFAULTS_H
-
-extern const char *default_server;
-extern const unsigned short default_port;
-extern const char *default_nick;
-
-#endif
exit(EXIT_FAILURE); \
} while (0)
+#define debug(...) do { \
+ fprintf(stderr, __VA_ARGS__); \
+} while (0)
+
#endif
--- /dev/null
+/* -*- conf-unix-*- */
+autogen definitions query.tpl;
+
+query = {
+ action = "nick_quit";
+ format = "foobar %s";
+};
--- /dev/null
+[+ autogen5 template h +]
+/*
+[+ (gpl "GNU Thales" " * " ) +]
+*/
+/*
+[+ (dne " * ") +]
+*/
+[+ (make-header-guard "") +]
+
+[+ FOR query "" +]
+#define WRITER_[+ (string-upcase (get "action")) +] "{[+ (get "action") +]}(%s)[+ (get "format") +]"
+[+ ENDFOR query +]
+#endif /* [+ (. header-guard) +] */
+++ /dev/null
-# -*- conf-unix-*-
-autogen definitions init_query;
-query = {
- value = "CREATE TABLE IF NOT EXISTS channel ("
- "chanid int unsigned NOT NULL auto_increment,"
- "channel varchar(33) binary NOT NULL default '',"
- "topic text,"
- "topicauthor varchar(31) default NULL,"
- "topictime datetime default NULL,"
- "PRIMARY KEY (chanid),"
- "UNIQUE KEY channel (channel))";
-
- error_msg = "Failed to create channel table.";
-};
-
-query = {
- value = "CREATE TABLE IF NOT EXISTS user ("
- "nickid int unsigned NOT NULL auto_increment,"
- "nick varchar(31) NOT NULL default '',"
- "realname varchar(51) NOT NULL default '',"
- "hostname varchar(64) NOT NULL default '',"
- "hiddenhostname varchar(64) NOT NULL default '',"
- "username varchar(11) NOT NULL default '',"
- "swhois varchar(32) NOT NULL default '',"
- "connecttime datetime NOT NULL default '0000-00-00 00:00:00',"
- "servid int unsigned NOT NULL default '0',"
- "away enum('Y','N') NOT NULL default 'N',"
- "awaymsg text,"
- "online enum('Y','N') NOT NULL DEFAULT 'Y',"
- "lastquit datetime default NULL,"
- "PRIMARY KEY (nickid),"
- "UNIQUE KEY nick (nick),"
- "KEY servid (servid))";
-
- error_msg = "Failed to create user table.";
-};
-
-query = {
- value = "CREATE TABLE IF NOT EXISTS server ("
- "servid int unsigned NOT NULL auto_increment,"
- "server varchar(64) NOT NULL default '',"
- "connecttime datetime default NULL,"
- "PRIMARY KEY (servid),"
- "UNIQUE KEY server (server))";
-
- error_msg = "Failed to create server table.";
-};
-
-query = {
- value = "CREATE TABLE IF NOT EXISTS presence ("
- "nickid int unsigned NOT NULL default '0',"
- "chanid int unsigned NOT NULL default '0',"
- "servid int unsigned NOT NULL default '0',"
- "PRIMARY KEY (nickid,chanid,servid),"
- "KEY nickid (nickid),"
- "KEY chanid (chanid))";
-
- error_msg = "Failed to create presence table.";
-};
+++ /dev/null
-[+autogen5 template h c +][+DEFINE
-GPL +]/*
-[+ (gpl "GNU Thales" " * " ) +]
- */
-[+ENDDEF +][+DEFINE
-DO_NOT_EDIT +]/*
-[+(dne " * ") +]
-*/
-[+ENDDEF +][+
-CASE (suffix) +][+
-== h +][+ DO_NOT_EDIT +]
-[+GPL+]
-[+ (make-header-guard "") +]
-
-#define INIT_QUERIES_COUNT [+ (count "query") +]
-extern char const *init_queries[ INIT_QUERIES_COUNT ];
-extern char const *init_queries_error_messages[ INIT_QUERIES_COUNT];
-#endif /* [+ (. header-guard) +] */ [+
-== c +][+ DO_NOT_EDIT +]
-[+ GPL +]
-
-#include "[+ (. header-file) +]"
-
-char const *init_queries[] = { [+
-FOR query "," +]
- "[+ value +]"[+
-ENDFOR query +]
-};
-
-char const *init_queries_error_messages[] = { [+
-FOR query "," +]
- "[+ error_msg +]"[+
-ENDFOR query +]
-};
-
-[+ESAC +]
#include "irc.h"
+#include <stdlib.h>
#include <libircclient/libircclient.h>
#include <libircclient/libirc_rfcnumeric.h>
#include <stdlib.h>
#include <string.h>
-#include "defaults.h"
+#include <assert.h>
+#include <signal.h>
+#include <cmd.h>
#include "error.h"
-#include "utility.h"
-#include "sentry.h"
+#include "writer.h"
+
+static volatile sig_atomic_t exit_flag;
+
+
+static inline void
+check_disconnect (irc_session_t * session)
+{
+ if (exit_flag)
+ irc_disconnect (session);
+}
+
+static inline const char *
+purge_nick (const char *nick)
+{
+ enum
+ { nickname_max_length = 256, max_simultaneous_calls = 8 };
+ static char buffer[max_simultaneous_calls][nickname_max_length];
+ static int call_index = 0;
+ call_index = (call_index + 1) % max_simultaneous_calls;
+ irc_target_get_nick (nick, buffer[call_index], nickname_max_length);
+ return buffer[call_index];
+}
-#define EVENT_CALLBACK(function_name) void \
+#define EVENT_CALLBACK(function_name) void \
function_name (irc_session_t * session, const char *event, \
const char *origin, const char **params, unsigned int count)
-struct context {
- SENTRY *sentry;
- const struct irc_options *opts;
-};
+EVENT_CALLBACK (event_part)
+{
+ const struct work_options *context = irc_get_ctx (session);
+ const char *nickname = purge_nick (origin);
+ const char *channel = *params;
+ const char *reason = params[1];
+
+ writer_channel_presence_remove (context, channel, nickname);
+ check_disconnect (session);
+}
+
+EVENT_CALLBACK (event_topic)
+{
+ const struct work_options *context = irc_get_ctx (session);
+ const char *nickname = purge_nick (origin);
+ const char *channel = *params;
+ const char *new_topic = params[1];
+
+ writer_channel_topic_update (context, channel, nickname, new_topic);
+}
+
+EVENT_CALLBACK (event_kick)
+{
+ const struct work_options *context = irc_get_ctx (session);
+ const char *kicker = purge_nick (origin);
+ const char *channel = *params;
+ const char *victim = purge_nick (params[1]);
+ const char *reason = params[2];
+
+ writer_channel_presence_remove (context, channel, victim);
+}
+
+EVENT_CALLBACK (event_nick)
+{
+ const struct work_options *context = irc_get_ctx (session);
+ const char *oldnick = purge_nick (origin);
+ const char *newnick = purge_nick (*params);
+
+
+ writer_nick_change (context, oldnick, newnick);
+}
-EVENT_CALLBACK(event_nick)
+static
+EVENT_CALLBACK (event_quit)
{
+ const struct work_options *context = irc_get_ctx (session);
+ const char *nickname = purge_nick (origin);
+ writer_nick_quit (context, nickname);
}
static
EVENT_CALLBACK (event_join)
{
- const char *nickname = origin;
+ const struct work_options *context = irc_get_ctx (session);
+ const char *nickname = purge_nick (origin);
const char *channel = *params;
- const struct context *ctx = irc_get_ctx(session);
+ const char *own_nickname = context->nickname;
- printf ("%s joined %s\n", nickname, channel);
- fflush(stdout);
- sentry_channel_presence_clear(ctx, channel);
- irc_cmd_names(session, channel);
+ if (!strcmp (own_nickname, nickname))
+ writer_channel_presence_clear (context, channel);
+ else
+ writer_channel_presence_add (context, channel, nickname);
}
static
EVENT_CALLBACK (event_channel)
{
+ const struct work_options *context = irc_get_ctx (session);
+ const char *nickname = purge_nick (origin);
+ const char *channel = *params;
+ const char *text = params[1];
+ debug ("%s", text);
}
static inline void
-event_numeric_namreply(struct context *context, const char *channel,
- const char *nicknames)
+event_numeric_namreply (irc_session_t * session, const char *channel,
+ const char *nicknames)
{
- char *nicknames_buf = strdup(nicknames);
+ struct work_options *context = irc_get_ctx (session);
+ char *nicknames_buf = strdup (nicknames);
- for (const char *nickname = strtok(nicknames_buf, " ");
- nickname;
- nickname = strtok(NULL, " "))
+ for (const char *nickname = strtok (nicknames_buf, " ");
+ nickname; nickname = strtok (NULL, " "))
{
- sentry_channel_presence_add(context->sentry, channel, nickname);
+ writer_channel_presence_add (context, channel, purge_nick (nickname));
+ irc_cmd_whois (session, nickname);
}
- free(nicknames_buf);
+ free (nicknames_buf);
+}
+
+static inline void
+event_numeric_whoisuser (const char *nickname,
+ const char *hostname, const char *server)
+{
+
}
+#define NUMERIC_OUTPUT_ARGS() \
+ fprintf(stderr, "*** Origin: %s ***\n", origin); \
+ fprintf(stderr, "*** Parameters: ***\n"); \
+ for (int ne_index = 0; ne_index != count; ne_index++) \
+ fprintf(stderr, "%s\n", params[ne_index]); \
+ fprintf(stderr, "*********\n");
+
static void
event_numeric (irc_session_t * session, unsigned int
event, const char *origin, const char **params,
unsigned int count)
{
- struct context *context = irc_get_ctx(session);
-
- switch (event) {
- case LIBIRC_RFC_RPL_NAMREPLY:
- assert(count >= 4);
- const char *channel = params[2];
- const char *nicknames = params[3];
- event_numeric_namreply(context, channel, nicknames);
- break;
- }
+ switch (event)
+ {
+ case LIBIRC_RFC_RPL_NAMREPLY:
+ assert (count >= 4);
+ const char *channel = params[2];
+ const char *nicknames = params[3];
+ event_numeric_namreply (session, channel, nicknames);
+ break;
+ case LIBIRC_RFC_RPL_WHOISUSER:
+ assert (count == 6);
+ const char *server = origin;
+ const char *nickname = params[1];
+ const char *hostname = params[3];
+ const char *realname = params[5];
+ event_numeric_whoisuser (nickname, hostname, server);
+ NUMERIC_OUTPUT_ARGS ();
+ break;
+ }
}
static
EVENT_CALLBACK (event_connect)
{
- const struct context *ctx = irc_get_ctx (session);
- printf("Connected!");
- for (char **chan = ctx->opts->channels; *chan; ++chan) {
- printf("sending connect request for %s\n", *chan);
+ const struct work_options *context = irc_get_ctx (session);
+ debug ("Connected!");
+ for (char **chan = context->channels; *chan; ++chan)
irc_cmd_join (session, *chan, NULL);
- }
- fflush(stdout);
}
/* Question to libircclient. Why not const? */
.event_join = event_join,
.event_connect = event_connect,
.event_numeric = event_numeric,
- .event_nick = event_nick
+ .event_nick = event_nick
};
+#define check_irc_error(session, err) if (err) {fatal ("error = %d, %s", err, irc_strerror (irc_errno (session))); }
bool
-start_listen_irc (const struct irc_options *opts,
- SENTRY *sentry)
+client_start_listen (const struct work_options *opts)
{
irc_session_t *session = irc_create_session (&callbacks);
- struct context context = {
- .sentry = sentry,
- .opts = opts
- };
if (!session)
fatal ("Failed to create session");
- irc_set_ctx (session, &context);
- int error = irc_connect (session,
- opts->server ? opts->server : default_server,
- opts->port ? opts->port : default_port, NULL, /* Password*/
- opts->nick ? opts->nick : default_nick, NULL,
- NULL);
- if (error)
- fatal ("error = %d, %s", error, irc_strerror (irc_errno (session)));
- error = irc_run (session);
- if (error)
- fatal ("error = %d, %s", error, irc_strerror (irc_errno (session)));
+
+ irc_set_ctx (session, opts);
+
+ int err = irc_connect (session,
+ opts->server, opts->port, NULL, /* Password */
+ opts->nickname, NULL, NULL);
+ check_irc_error (session, err);
+
+ err = irc_run (session);
+ check_irc_error (session, err);
+
irc_destroy_session (session);
return true;
}
+
+#undef check_irc_error
+
+void
+client_stop_listen (void)
+{
+ exit_flag = 1;
+}
#ifndef IRC_H
#define IRC_H
#include <stdbool.h>
-#include "cmd.h"
-#include "sentry.h"
-struct irc_user {
+struct work_options;
+struct ircclient
+{
char *nickname;
char *realname;
+ char *server;
+ char ipv4[8]; /* 8 hex digits */
+ bool ready;
};
-bool start_listen_irc(const struct irc_options *opts, SENTRY *sentry);
-
+bool client_start_listen (const struct work_options *opts);
+void client_stop_listen (void);
#endif
--- /dev/null
+#ifndef CLIENTSET_H
+#define CLIENTSET_H
+#include "irc.h"
+
+
+typedef struct ircclient_set ircclient_set;
+ircclient_set *ircclient_set_new();
+struct irc_client* ircclient_set_find(ircclient_set *set, const char *nickname);
+void ircclient_set_remove(ircclient_set *set, const char *nickname);
+void ircclient_set_dispose(ircclient_set *set);
+
+#endif
-/* Main program of GNU Thales. Copyright (C)
-2012 Free Software Foundation, Inc. This file is part of GNU Thales.
-
-GNU Thales is free software; you can redistribute it and/or modify it under the
-terms of the GNU General Public License as published by the Free Software
-Foundation; either version 3 of the License, or (at your option) any later
-version.
-
-GNU Thales 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 for more details.
-
-You should have received a copy of the GNU General Public License along with
-this program. If not, see <http://www.gnu.org/licenses/>. */
+/*
+ * Main program of GNU Thales. Copyright (C)
+ * 2012 Free Software Foundation, Inc. This file is part of GNU Thales.
+ *
+ * GNU Thales is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * GNU Thales 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
#include <config.h>
#include <stdio.h>
#include "cmd.h"
#include "error.h"
#include "irc.h"
-#include "sentry.h"
int
main (int argc, char **argv)
{
- struct irc_options irc_opts = { 0 };
- struct mysql_options mysql_opts = { 0 };
- struct config_options config_opts = { 0 };
-
-
- parse_cmd_options (&irc_opts, &config_opts, argc, argv);
- FILE *config_file = config_opts.conf_filename ? fopen (config_opts.conf_filename, "r")
- : default_config_file ();
-
- if (!config_file)
- fatal ("failed to open config file");
-
- parse_mysql_options(&mysql_opts, config_file);
-
-SENTRY *sentry = sentry_initialize(&mysql_opts, irc_opts.server);
-#warning "mysql is not used"
-/* if (!sentry) */
-/* fatal("failed to connect to database"); */
+ struct work_options work_opts = { 0 };
+ parse_cmd_options (&work_opts, argc, argv);
- start_listen_irc(&irc_opts, sentry);
+ setbuf(stdout, NULL); /* Just in case. */
+ client_start_listen (&work_opts);
return 0;
}
+++ /dev/null
-# -*- conf-unix-*-
-autogen definitions query;
-query = {
- def = "CHANNEL_PRESENCE_CLEAR";
- value = "clear?!";
- error_msg = "Failed to clear?!";
- comment = "Optional";
-};
-query = {
- def = "CHANNEL_PRESENCE_ADD";
- value = "add?!";
- error_msg = "Failed to add?!";
-};
\ No newline at end of file
+++ /dev/null
-[+autogen5 template h c +][+DEFINE
-GPL +]/*
-[+ (gpl "GNU Thales" " * " ) +]
- */
-[+ENDDEF +][+DEFINE
-DO_NOT_EDIT +]/*
-[+(dne " * ") +]
-*/
-[+ENDDEF +][+
-CASE (suffix) +][+
-== h +][+ DO_NOT_EDIT +]
-[+GPL+]
-[+ (make-header-guard "") +]
-
-[+FOR query "" +]
-/* [+ comment +] */
-#define QUERY_[+def+] [+ (for-index) +]
-[+ENDFOR query +]
-
-#define QUERIES_COUNT [+ (count "query") +]
-extern char const *queries[ QUERIES_COUNT ];
-extern char const *queries_error_messages[ QUERIES_COUNT];
-#endif /* [+ (. header-guard) +] */ [+
-== c +][+ DO_NOT_EDIT +]
-[+ GPL +]
-
-#include "[+ (. header-file) +]"
-
-char const *queries[] = { [+
-FOR query "," +]
- "[+ value +]"[+
-ENDFOR query +]
-};
-
-char const *queries_error_messages[] = { [+
-FOR query "," +]
- "[+ error_msg +]"[+
-ENDFOR query +]
-};
-
-[+ESAC +]
+++ /dev/null
-#include "sentry.h"
-#include <xalloc.h>
-#include <stdbool.h>
-#include <dbi/dbi.h>
-#include "cmd.h"
-#include "init_query.h"
-
-struct sentry
-{
- char *unused;
-};
-
-static inline bool
-initialize_tables(MYSQL *db_handle)
-{
- for (const char *query = *init_queries; *query; ++query)
- if (!mysql_query(db_handle, query))
- return false;
- return true;
-}
-
-SENTRY *
-sentry_initialize (const struct mysql_options *opts, const char *server)
-{
- MYSQL db_handle;
- mysql_init (&db_handle);
- if (!mysql_real_connect (&db_handle, opts->host, opts->username,
- opts->password, opts->database, opts->port,
- NULL, 0))
- {
- fprintf(stderr, "Failed to connect to database: Error: %s\n",
- mysql_error(&db_handle));
- goto connect;
- }
- if (!initialize_tables(&db_handle)) {
- fprintf(stderr, "Failed to connect to database: Error: %s\n",
- mysql_error(&db_handle));
- goto tables;
- }
-
- struct sentry *new = xmalloc (sizeof *new);
-
- new->db_handle = db_handle;
- new->server = xstrdup(server);
- return new;
-
- tables:
- mysql_close(&db_handle);
- connect:
- return NULL;
-}
-
-void
-sentry_channel_presence_clear(SENTRY *sentry, const char *channel)
-{
- static const char *query =
-}
-
-void
-sentry_channel_presence_add(SENTRY *sentry, const char *channel,
- const char *nickname)
-{
- const char *query = "INSERT INTO presence VALUES (nickid, chanid, servid) where"
-
-}
+++ /dev/null
-#ifndef SENTRY_H
-#define SENTRY_H
-#include <stdbool.h>
-struct db_options;
-struct sentry;
-typedef struct sentry SENTRY;
-
-SENTRY *sentry_initialize(const struct db_options *opts, const char *server);
-void sentry_channel_presence_clear(SENTRY *sentry, const char *channel);
-void sentry_channel_presence_add(SENTRY *sentry, const char *channel,
- const char *nickname);
-#endif
+++ /dev/null
-#ifndef UTILITY_H
-#define UTILITY_H
-#include <xalloc.h>
-#include <xstrndup.h>
-
-#define countof(x) sizeof(x)/sizeof(0[x])
-static inline void *
-xrangedup (const void *begin, const void *end)
-{
- return xstrndup (begin, (char *) end - (char *) begin);
-}
-static inline char*
-xstrdup_safe(const char *ptr)
-{
- return ptr ? xstrdup(ptr) : NULL;
-}
-
-#endif
--- /dev/null
+#include <xalloc.h>
+#include <stdbool.h>
+#include "cmd.h"
+
+#define writer_printf(context, fmt, ...) printf("%s/%s:%d\t" fmt, \
+ __func__+7, /* Remove `writer_` prefix */ \
+ context->server, context->port, __VA_ARGS__)
+void
+writer_channel_presence_clear(struct work_options *context, const char *channel)
+{
+ writer_printf(context, "%s\n", channel);
+}
+
+void
+writer_channel_presence_add(struct work_options *context, const char *channel,
+ const char *nickname)
+{
+ writer_printf(context, "%s\t%s\n", channel, nickname);
+}
+
+void
+writer_channel_presence_remove(struct work_options *context, const char *channel,
+ const char *nickname)
+{
+ writer_printf(context, "%s\t%s\n", channel, nickname);
+}
+void
+writer_channel_topic_update(struct work_options *context, const char *channel,
+ const char *nickname, const char *new_topic)
+{
+ writer_printf(context, "%s\t%s\t%s\n", channel, nickname, new_topic);
+}
+void
+writer_nick_change(struct work_options *context, const char *oldnick, const char *newnick)
+{
+ writer_printf(context, "%s\t%s\n", oldnick, newnick);
+}
+void
+writer_nick_quit(struct work_options *context, const char *nickname)
+{
+ writer_printf(context, "%s\n", nickname);
+}
--- /dev/null
+#ifndef WRITER_H
+#define WRITER_H
+#include <stdbool.h>
+struct work_options;
+
+void writer_channel_presence_clear(const struct work_options *context, const char *channel);
+void writer_channel_presence_add(const struct work_options *context, const char *channel,
+ const char *nickname);
+void writer_channel_presence_remove(const struct work_options *context, const char *channel,
+ const char *nickname);
+void writer_channel_topic_update(const struct work_options *context, const char *channel,
+ const char *nickname, const char *new_topic);
+void writer_nick_change(const struct work_options *context, const char *oldnick, const char *newnick);
+void writer_nick_quit(const struct work_options *context, const char *nickname);
+
+#endif