#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
+#include "utility.h"
static void
printf_option (const char *option, const char *description)
}
void
-parse_cmdopts (struct cmd_options *opts, int argc, char **argv)
+parse_cmdopts (struct irc_options *opts, int argc, char **argv)
{
const char *optstr = "hvs:p:C:n:";
const struct option longopts[] = {
}
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], "w")))
+ return config_file;
+ return NULL;
+}
+
+static 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"));
+
+}
#ifndef CMD_H
#define CMD_H
-struct cmd_options {
- const char *conf_filename;
+struct irc_options {
const char *server;
const char *nick;
unsigned short port;
- char **channels; // NULL-terminated
+ char **channels;
};
-void parse_cmdopts(struct cmd_options *opts, int argc, char **argv);
+struct mysql_options {
+ const char *host;
+ const char *username;
+ const char *password;
+ const char *database;
+ unsigned short int port;
+};
+
+FILE* default_config_file(void);
+void parse_cmd_options(struct irc_options *opts, int argc, char **argv);
+void parse_mysql_options(struct mysql_options *opts, FILE *stream);
#endif
+++ /dev/null
-/* Configuration file parsing 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 Make 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 "conf.h"
-#include <stdbool.h>
-#include <stdlib.h>
-#include <envz.h>
-#include <ctype.h>
-
-#define countof(x) sizeof(x)/sizeof(0[x])
-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], "w")))
- return config_file;
- return NULL;
-}
-
-
-static char *
-worddup_between(const char *line, char ldel, char rdel)
-{
- char *left = strchr(line, ldel);
- char *right = strchr(line, rdel);
-
- if (left && right)
- return strndup(left + 1, right - left - 1);
- else
- return NULL;
-}
-static bool
-parse_header(const char *line, char **type, char **name)
-{
- free(*type);
- free(*name);
-
- *type = worddup_between(line, '[', ']');
- *name = worddup_between(line, '{', '}');
-
- return type && name;
-}
-
-static inline void
-syntax_error(size_t lineno)
-{
- fprintf(stderr, "config_file: syntax error on line %d\n", (int) lineno);
- exit(EXIT_FAILURE);
-}
-static inline void
-initialization_error(const char *type, const char *name)
-{
- fprintf(stderr, "module %s: failed to initialize with config `%s'\n",
- type, name);
- exit(EXIT_FAILURE);
-}
-static inline void
-clear_envz(struct envz *env)
-{
- free(env->envz);
-
- env->envz = NULL;
- env->envz_len = 0;
-}
-static inline bool
-all(const char *str, int(*test)(int))
-{
- for (const char *p = str; *p; ++p)
- if (!(*test)(*p))
- return false;
- return true;
-}
-static inline bool
-is_comment(const char *line)
-{
- return line[0] == '#' || all(line, isspace);
-}
-static inline void
-xinit_module(module_initializer init, const char *type,
- const char *name, const struct envz *env)
-{
- if (!type || !name)
- return;
- (*init)(type, name, env);
-}
-void
-parse_config(FILE *stream, module_initializer init)
-{
- char *line, *name, *type;
- size_t line_size = 0;
- struct envz env = {NULL, 0};
-
- line = name = type = NULL;
- for (size_t lineno = 1; getline(&line, &line_size, stream)!= EOF; lineno++)
- switch (line[0])
- {
- case '[': /* header */
- xinit_module(init, type, name, &env);
- clear_envz(&env);
- if (!parse_header(line, &type, &name))
- syntax_error(lineno);
- break;
- default:
- if (!is_comment(line))
- argz_add(&env.envz, &env.envz_len, line);
- }
- xinit_module(init, type, name, &env);
- clear_envz(&env);
- free(line);
-}
+++ /dev/null
-/* Configuration file parsing 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/>. */
-
-#ifndef CONF_H
-#define CONF_H
-#include <stdio.h>
-#include <stdbool.h>
-#include <envz.h>
-struct envz {
- char *envz;
- size_t envz_len;
-};
-#define DECLARE_ENVZ_GET(envz, key) const char *key = \
- envz_get((envz)->envz, ((envz)->envz_len), #key)
-
-
-typedef void (*module_initializer)(const char *type,
- const char *name, const struct envz *env);
-FILE* default_config_file(void);
-void parse_config(FILE *stream, module_initializer init);
-#endif
#include <stdbool.h>
#include "cmd.h"
#include "list.h"
+struct irc_user {
+ char *nickname;
+ char *realname;
+};
bool start_listen_irc(const struct cmd_options *opts,
const struct list_head *workers);
+++ /dev/null
-#ifndef __LIST_H
-#define __LIST_H
-
-/* This file is from Linux Kernel (include/linux/list.h)
- * and modified by simply removing hardware prefetching of list items.
- * Here by copyright, credits attributed to wherever they belong.
- * Kulesh Shanmugasundaram (kulesh [squiggly] isis.poly.edu)
- */
-
-/*
- * Simple doubly linked list implementation.
- *
- * Some of the internal functions ("__xxx") are useful when
- * manipulating whole lists rather than single entries, as
- * sometimes we already know the next/prev entries and we can
- * generate better code by using them directly rather than
- * using the generic single-entry routines.
- */
-
-struct list_head {
- struct list_head *next, *prev;
-};
-
-#define LIST_HEAD_INIT(name) { &(name), &(name) }
-
-#define LIST_HEAD(name) \
- struct list_head name = LIST_HEAD_INIT(name)
-
-#define INIT_LIST_HEAD(ptr) do { \
- (ptr)->next = (ptr); (ptr)->prev = (ptr); \
-} while (0)
-
-/*
- * Insert a new entry between two known consecutive entries.
- *
- * This is only for internal list manipulation where we know
- * the prev/next entries already!
- */
-static inline void __list_add(struct list_head *new,
- struct list_head *prev,
- struct list_head *next)
-{
- next->prev = new;
- new->next = next;
- new->prev = prev;
- prev->next = new;
-}
-
-/**
- * list_add - add a new entry
- * @new: new entry to be added
- * @head: list head to add it after
- *
- * Insert a new entry after the specified head.
- * This is good for implementing stacks.
- */
-static inline void list_add(struct list_head *new, struct list_head *head)
-{
- __list_add(new, head, head->next);
-}
-
-/**
- * list_add_tail - add a new entry
- * @new: new entry to be added
- * @head: list head to add it before
- *
- * Insert a new entry before the specified head.
- * This is useful for implementing queues.
- */
-static inline void list_add_tail(struct list_head *new, struct list_head *head)
-{
- __list_add(new, head->prev, head);
-}
-
-/*
- * Delete a list entry by making the prev/next entries
- * point to each other.
- *
- * This is only for internal list manipulation where we know
- * the prev/next entries already!
- */
-static inline void __list_del(struct list_head *prev, struct list_head *next)
-{
- next->prev = prev;
- prev->next = next;
-}
-
-/**
- * list_del - deletes entry from list.
- * @entry: the element to delete from the list.
- * Note: list_empty on entry does not return true after this, the entry is in an undefined state.
- */
-static inline void list_del(struct list_head *entry)
-{
- __list_del(entry->prev, entry->next);
- entry->next = (void *) 0;
- entry->prev = (void *) 0;
-}
-
-/**
- * list_del_init - deletes entry from list and reinitialize it.
- * @entry: the element to delete from the list.
- */
-static inline void list_del_init(struct list_head *entry)
-{
- __list_del(entry->prev, entry->next);
- INIT_LIST_HEAD(entry);
-}
-
-/**
- * list_move - delete from one list and add as another's head
- * @list: the entry to move
- * @head: the head that will precede our entry
- */
-static inline void list_move(struct list_head *list, struct list_head *head)
-{
- __list_del(list->prev, list->next);
- list_add(list, head);
-}
-
-/**
- * list_move_tail - delete from one list and add as another's tail
- * @list: the entry to move
- * @head: the head that will follow our entry
- */
-static inline void list_move_tail(struct list_head *list,
- struct list_head *head)
-{
- __list_del(list->prev, list->next);
- list_add_tail(list, head);
-}
-
-/**
- * list_empty - tests whether a list is empty
- * @head: the list to test.
- */
-static inline int list_empty(struct list_head *head)
-{
- return head->next == head;
-}
-
-static inline void __list_splice(struct list_head *list,
- struct list_head *head)
-{
- struct list_head *first = list->next;
- struct list_head *last = list->prev;
- struct list_head *at = head->next;
-
- first->prev = head;
- head->next = first;
-
- last->next = at;
- at->prev = last;
-}
-
-/**
- * list_splice - join two lists
- * @list: the new list to add.
- * @head: the place to add it in the first list.
- */
-static inline void list_splice(struct list_head *list, struct list_head *head)
-{
- if (!list_empty(list))
- __list_splice(list, head);
-}
-
-/**
- * list_splice_init - join two lists and reinitialise the emptied list.
- * @list: the new list to add.
- * @head: the place to add it in the first list.
- *
- * The list at @list is reinitialised
- */
-static inline void list_splice_init(struct list_head *list,
- struct list_head *head)
-{
- if (!list_empty(list)) {
- __list_splice(list, head);
- INIT_LIST_HEAD(list);
- }
-}
-
-/**
- * list_entry - get the struct for this entry
- * @ptr: the &struct list_head pointer.
- * @type: the type of the struct this is embedded in.
- * @member: the name of the list_struct within the struct.
- */
-#define list_entry(ptr, type, member) \
- ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
-
-/**
- * list_for_each - iterate over a list
- * @pos: the &struct list_head to use as a loop counter.
- * @head: the head for your list.
- */
-#define list_for_each(pos, head) \
- for (pos = (head)->next; pos != (head); \
- pos = pos->next)
-/**
- * list_for_each_prev - iterate over a list backwards
- * @pos: the &struct list_head to use as a loop counter.
- * @head: the head for your list.
- */
-#define list_for_each_prev(pos, head) \
- for (pos = (head)->prev; pos != (head); \
- pos = pos->prev)
-
-/**
- * list_for_each_safe - iterate over a list safe against removal of list entry
- * @pos: the &struct list_head to use as a loop counter.
- * @n: another &struct list_head to use as temporary storage
- * @head: the head for your list.
- */
-#define list_for_each_safe(pos, n, head) \
- for (pos = (head)->next, n = pos->next; pos != (head); \
- pos = n, n = pos->next)
-
-/**
- * list_for_each_entry - iterate over list of given type
- * @pos: the type * to use as a loop counter.
- * @head: the head for your list.
- * @member: the name of the list_struct within the struct.
- */
-#define list_for_each_entry(pos, head, member) \
- for (pos = list_entry((head)->next, typeof(*pos), member); \
- &pos->member != (head); \
- pos = list_entry(pos->member.next, typeof(*pos), member))
-
-/**
- * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
- * @pos: the type * to use as a loop counter.
- * @n: another type * to use as temporary storage
- * @head: the head for your list.
- * @member: the name of the list_struct within the struct.
- */
-#define list_for_each_entry_safe(pos, n, head, member) \
- for (pos = list_entry((head)->next, typeof(*pos), member), \
- n = list_entry(pos->member.next, typeof(*pos), member); \
- &pos->member != (head); \
- pos = n, n = list_entry(n->member.next, typeof(*n), member))
-
-
-#endif
#include "workers_registration.h"
#include "irc.h"
-static LIST_HEAD (workers);
-static void
-module_initialization_dispatcher (const char *type,
- const char *name, const struct envz *env)
-{
- const struct worker_creator *cr = worker_creator_by_type (type);
- struct worker *worker;
-
- if (!cr)
- fatal ("No module of type `%s' registered", type);
-
- worker = (*cr->creator) (env);
- if (!worker)
- fatal ("Failed to initiailize modude of type %s with name %s",
- type, name);
-
- list_add (&worker->list, &workers);
-}
-
int
main (int argc, char **argv)
{
- struct cmd_options opts = { 0, };
+ struct cmd_options cmd_opts = { 0, };
+ struct mysql_options mysql_opts = { 0, };
FILE *config_file;
- parse_cmdopts (&opts, argc, argv);
- config_file = opts.conf_filename ?
- fopen (opts.conf_filename, "r") : default_config_file ();
+ parse_cmdopts (&cmd_opts, argc, argv);
+ config_file = cmd_opts.conf_filename ? fopen (opts.conf_filename, "r")
+ : default_config_file ();
+
if (!config_file)
fatal ("failed to open config file");
- init_worker_creators ();
- parse_config (config_file, &module_initialization_dispatcher);
- start_listen_irc (&opts, &workers);
+
+ parse_mysql_options(&mysql_opts);
+ start_listen_irc (&cmd_opts, &workers);
return 0;
}
#include "mysql_sentry.h"
#include <mysql/mysql.h>
-#include "sentry.h"
#include <xalloc.h>
+#include "cmd.h"
-struct statements {
- MYSQL_RES *last_activity;
-};
-struct mysql_sentry
+typedef struct sentry
{
- struct sentry sentry;
MYSQL db_handle;
- struct statements statements;
-};
-static void mysql_sentry_join_event (struct sentry *, const char *user,
- const char *channel);
-static void mysql_sentry_message_event (const struct sentry *,
- const char *user, const char *channel,
- const char *msg);
-static void mysql_sentry_part_event (struct sentry *, const char *user,
- const char *channel);
+} SENTRY;
-static inline void
-initialize_vtable (struct sentry *sentry)
+SENTRY *
+sentry_initialize (const struct mysql_options *opts)
{
- sentry->join_event = mysql_sentry_join_event;
- sentry->message_event = mysql_sentry_message_event;
- sentry->part_event = mysql_sentry_part_event;
-}
-
-static inline
-
-struct sentry *
-create_mysql_sentry (const struct envz *envz)
-{
- struct mysql_sentry *new = xmalloc (sizeof *new);
- DECLARE_ENVZ_GET (envz, host);
- DECLARE_ENVZ_GET (envz, username);
- DECLARE_ENVZ_GET (envz, password);
- DECLARE_ENVZ_GET(envz, prefix);
- DECLARE_ENVZ_GET(envz, database);
- initialize_vtable (&new->sentry);
-
- if (!mysql_connect(&new->db_handle, host, username, password)) {
- warning("Failed to connect to mysql server with username %s", username);
- free(new);
- return NULL;
- }
- if (!database || mysql_select_db(&new->db_handle, database)) {
- warning("Failed to select database %s", database);
- free(new);
- return NULL;
- }
-
-
- // mysql_connect(new->db_handle,
+ MYSQL db_handle;
+ mysql_init (&db_handle);
+ if (!mysql_real_connect (&db_handle, opts->host, opts->user,
+ opts->password, opts->database, opts->port,
+ NULL, 0))
+ {
+ fprintf(stderr, "Failed to connect to database: Error: %s\n",
+ mysql_error(&mysql));
+ return NULL;
+ }
+ struct sentry *new = xmalloc (sizeof *new);
+ new->db_handle = db_handle;
+ return new;
}
#ifndef MYSQL_SENTRY_H
#define MYSQL_SENTRY_H
-#include "sentry.h"
-#include "conf.h"
+struct mysql_options;
+struct sentry;
+typedef struct sentry SENTRY;
-#define sentry_entry(ptr,type,name) (type*)((char *)ptr - offsetof(type,name))
-struct sentry* create_mysql_sentry(const struct envz *);
+SENTRY *sentry_initialize(const struct mysql_options *opts);
#endif
+++ /dev/null
-/* Main modules interface 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/>. */
-
-#ifndef SENTRY_H
-#define SENTRY_H
-
-#define sentry_entry(ptr,type,name) (type*)((char *)ptr - offsetof(type,name))
-struct sentry {
- void (*join_event)(struct sentry *, const char *user, const char *channel);
- void (*message_event)(const struct sentry *, const char *user,
- const char *channel, const char *msg);
- void (*part_event)(struct sentry *, const char *user, const char *channel);
-};
-#endif
#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 ? xstrndup(ptr) : NULL;
+}
#endif