Push some common logging code into src/log_support.c.
authorJelmer Vernooij <jelmer@samba.org>
Tue, 4 Sep 2007 20:42:40 +0000 (22:42 +0200)
committerJelmer Vernooij <jelmer@samba.org>
Tue, 4 Sep 2007 20:42:40 +0000 (22:42 +0200)
Makefile
NEWS
mods/log_custom.c
mods/log_irssi.c
src/ctrlproxy.h
src/log.c
src/log_support.c [new file with mode: 0644]
src/log_support.h [new file with mode: 0644]
src/main.c
src/network.c
src/settings.c

index c0e0f1d5a6caf2d30f891dd17f6e12acc9397e8a..62fde92f5136f5a33fb02fbf504e0d0e48c1884a 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -49,6 +49,7 @@ objs = src/network.o \
           src/help.o \
           src/repl_backends.o \
           src/listener.o \
+          src/log_support.o \
           $(SSL_OBJS)
 
 headers = src/admin.h \
@@ -60,6 +61,7 @@ headers = src/admin.h \
                  src/line.h \
                  src/linestack.h \
                  src/network.h \
+                 src/log_support.h \
                  src/repl.h \
                  src/settings.h \
                  src/ssl.h \
diff --git a/NEWS b/NEWS
index 6d41cce2c7722162fbab3d64f171877da6f52b82..277b26a0a14c59a824cc219cd0cae463fc9fbd41 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -24,6 +24,9 @@ Ctrlproxy 3.0.4 UNRELEASED
 
        * Start checking plugin versions.
 
+  INTERNALS
+
+    * Moved some common logging code to the core.
 
 Ctrlproxy 3.0.3 2007-07-22
 
index 520e98bcb0e8791170563effd64dfd3185470471..e5290114cc0f07641c7b3aed99cdb8116e1d125d 100644 (file)
 
 #define MAX_SUBST 256
 
-struct file_info {
-       FILE *file;
-       time_t last_used;
-};
-
 struct log_custom_data {
     char *logfilename;
     GKeyFile *kf;
+       struct log_support_context *log_ctx;
 };
 
-static GHashTable *files;
-
 /* Translation table */
 struct log_mapping {
        char *command;
@@ -114,12 +108,19 @@ static char *get_user(struct network *n, const struct line *l,
        char *nick = NULL;
        char *user = NULL;
 
-       if (l->origin != NULL) nick = g_strdup(l->origin);
-       if (nick != NULL) user = strchr(nick, '!');
-       if (user != NULL) { *user = '\0';user++; }
+       if (l->origin != NULL) 
+               nick = g_strdup(l->origin);
+       if (nick != NULL) 
+               user = strchr(nick, '!');
+       if (user != NULL) { 
+               *user = '\0'; 
+               user++; 
+       }
 
-       if (case_sensitive) return g_ascii_strdown(user, -1);
-       else return g_strdup(user);
+       if (case_sensitive) 
+               return g_ascii_strdown(user, -1);
+       else 
+               return g_strdup(user);
 }
 
 static char *get_monthname(struct network *n, const struct line *l, 
@@ -344,73 +345,23 @@ If appropriate:
  -- NICK: %r
  */
 
-static FILE *find_add_channel_file(struct log_custom_data *data, 
-                                                                  struct network *network, 
-                                                                  const struct line *l, 
-                                                                  const char *identifier, 
-                                                                  gboolean create_file) 
-{
-       char *n = NULL, *dn, *p;
-       struct file_info *fi;
-       if (data->logfilename == NULL) 
-               return NULL;
-
-       custom_subst(network, &n, data->logfilename, l, identifier, TRUE, TRUE);
-       fi = g_hash_table_lookup(files, n);
-
-       if (fi == NULL && create_file) {
-               dn = g_strdup(n);
-               
-               /* Only include directory-part */
-               p = strrchr(dn, '/');
-               if (p != NULL) 
-                       *p = '\0';
-
-               /* Check if directory needs to be created */
-               if (!g_file_test(dn, G_FILE_TEST_IS_DIR) && g_mkdir(dn, 0700) == -1) {
-                       log_network(LOG_ERROR, network, "Couldn't create directory %s for logging!", dn);
-                       g_free(dn);
-                       g_free(n);
-                       return NULL;
-               }
-               g_free(dn);
-
-               fi = g_new0(struct file_info, 1);
-               
-               /* Then open the correct filename */
-               fi->file = fopen(n, "a+");
-               if (fi->file == NULL) {
-                       log_network(LOG_ERROR, network, "Couldn't open file %s for logging!", n);
-                       g_free(n);
-                       g_free(fi);
-                       return NULL;
-               }
-               g_hash_table_insert(files, n, fi);
-       } else g_free(n);
-
-       if (fi == NULL)
-               return NULL;
-
-       fi->last_used = time(NULL);
-       return fi->file;
-}
-
 static void file_write_line(struct log_custom_data *data, struct network *network, const char *fmt,
-                                  const struct line *l, const char *t, gboolean create_file)
+                                  const struct line *l, const char *identifier, gboolean create_file)
 {
-       FILE *f;
        char *s;
+       char *n = NULL;
 
-       f = find_add_channel_file(data, network, l, t, create_file);
-       if (f == NULL) return;
+       custom_subst(network, &s, fmt, l, identifier, FALSE, FALSE);
 
-       custom_subst(network, &s, fmt, l, t, FALSE, FALSE);
+       if (data->logfilename == NULL) 
+               return;
 
-       fputs(s, f);
-       fputc('\n', f);
-       fflush(f);
+       custom_subst(network, &n, data->logfilename, l, identifier, TRUE, TRUE);
+
+       log_support_write(data->log_ctx, n, s);
 
        g_free(s);
+       g_free(n);
 }
 
 static void file_write_line_target(struct log_custom_data *data, struct network *network, const char *fmt,
@@ -438,10 +389,10 @@ static void file_write_target(struct log_custom_data *data,
        if (fmt == NULL) 
                return;
        
-       g_assert(l->args[0]);
-       g_assert(l->args[1]);
-       g_assert(network->state);
-       g_assert(network->state->me.nick);
+       g_assert(l->args[0] != NULL);
+       g_assert(l->args[1] != NULL);
+       g_assert(network->state != NULL);
+       g_assert(network->state->me.nick != NULL);
 
        if (!irccmp(&network->state->info, network->state->me.nick, l->args[1])) {
                if (l->origin != NULL)
@@ -478,7 +429,7 @@ static void file_write_channel_query(struct log_custom_data *data,
        if (l->origin == NULL) 
                return;
 
-       g_assert(n);
+       g_assert(n != NULL);
 
        fmt = g_key_file_get_string(data->kf, "log-custom", n, NULL);
        if (fmt == NULL) 
@@ -558,8 +509,10 @@ static gboolean log_custom_data(struct network *network, const struct line *l,
                        while (cont) {
                                n = strchr(p, ',');
 
-                               if (!n) cont = 0;
-                               else *n = '\0';
+                               if (n == NULL) 
+                                       cont = 0;
+                               else 
+                                       *n = '\0';
 
                                file_write_channel_only(data, network, "kick", l);
 
@@ -587,14 +540,6 @@ static gboolean log_custom_data(struct network *network, const struct line *l,
        return TRUE;
 }
 
-static void free_file_info(void *_data)
-{
-       struct file_info *data = _data;
-
-       fclose(data->file);
-       g_free(data);
-}
-
 static void load_config(struct global *global)
 {
        GKeyFile *kf = global->config->keyfile;
@@ -610,29 +555,12 @@ static void load_config(struct global *global)
        add_log_filter("log_custom", log_custom_data, data, 1000);
 
        data->logfilename = g_key_file_get_string(kf, "log-custom", "logfilename", NULL);
+       data->log_ctx = log_support_init();
        data->kf = kf;
 }
 
-#define CLEANUP_THRESHOLD (60 * 60 * 24)
-
-static gboolean eval_remove(gpointer key, gpointer value, gpointer user_data)
-{
-       struct file_info *fi = value;
-
-       return (fi->last_used < time(NULL) - CLEANUP_THRESHOLD);
-}
-
-static gboolean cleanup(void *_data)
-{
-       g_hash_table_foreach_remove(files, eval_remove, NULL);
-       return TRUE;
-}
-
 static gboolean init_plugin(void)
 {
-       files = g_hash_table_new_full(g_str_hash, g_str_equal, 
-                       g_free, free_file_info);
-       g_timeout_add(60 * 60, cleanup, NULL);
        register_load_config_notify(load_config);
        return TRUE;
 }
index 32af6142c3786fc91933678113d8e6fad5b86698..53fb3780437450b57ada376094c119875683c3f9 100644 (file)
 #include <sys/stat.h>
 #include <sys/types.h>
 
-static char *logfile = NULL;
-static GHashTable *files = NULL;
+static char *logbasedir = NULL;
+struct log_support_context *log_ctx = NULL;
 
-static FILE *find_add_channel_file(struct network *s, const char *name) 
+void strip_slashes(char *cn)
 {
-       char *n = NULL;
-       FILE *f;
-       char *hash_name;
        int i;
-       char *lowercase;
-
-       lowercase = g_ascii_strdown(name?name:"messages", -1);
-       hash_name = g_strdup_printf("%s/%s", s->info.name, lowercase);
-       g_free(lowercase);
-
-       f = g_hash_table_lookup(files, hash_name);
-       if (f == NULL) {
-               char *cn; 
-               const char *server_name;
+       for (i = 0; cn[i]; i++) 
+               if (cn[i] == '/') 
+                       cn[i] = '_';
 
-               server_name = s->info.name;
-
-               if (strchr(server_name, '/') != NULL) 
-                       server_name = strrchr(server_name, '/');
-
-               n = g_build_filename(logfile, server_name, NULL);
-               /* Check if directory needs to be created */
-               if (!g_file_test(n, G_FILE_TEST_IS_DIR) && g_mkdir(n, 0700) == -1) {
-                       log_network(LOG_ERROR, s, "Couldn't create directory %s for logging!", n);
-                       g_free(hash_name);
-                       g_free(n);
-                       return NULL;
-               }
-               g_free(n);
-               
-               /* Then open the correct filename */
-               cn = g_ascii_strdown(name != NULL?name:"messages", -1);
-               for (i = 0; cn[i]; i++) 
-                       if (cn[i] == '/') 
-                               cn[i] = '_';
-               n = g_build_filename(logfile, server_name, cn, NULL);
-               g_free(cn);
-               f = fopen(n, "a+");
-               if (f == NULL) {
-                       log_network(LOG_ERROR, s, "Couldn't open file %s for logging!", n);
-                       g_free(n);
-                       return NULL;
-               }
-               g_free(n);
-               g_hash_table_insert(files, hash_name, f);
-       } else g_free(hash_name);
-       g_assert(f);
-       return f;
 }
 
-static void target_vprintf(struct network *n, const char *name, 
+static void target_vprintf(struct network *s, const char *name, 
                                                   char *fmt, va_list ap)
 {
-       FILE *f = find_add_channel_file(n, name);
-       if (f != NULL) {
-               vfprintf(f, fmt, ap);
-               fflush(f);
-       }
+       char *lowercase;
+       char *text;
+       char *networkname;
+       char *hash_name;
+
+       lowercase = g_ascii_strdown(name != NULL?name:"messages", -1);
+       networkname = g_strdup(s->info.name);
+       strip_slashes(lowercase);
+       hash_name = g_build_filename(logbasedir, networkname, lowercase, NULL);
+       g_free(networkname);
+       g_free(lowercase);
+
+       /* Then open the correct filename */
+       text = g_strdup_vprintf(fmt, ap);
+       log_support_write(log_ctx, hash_name, text);
+       g_free(text);
+
+       g_free(hash_name);
 }
 
 static void target_printf(struct network *n, const char *name, 
@@ -221,27 +191,29 @@ static gboolean log_data(struct network *n, const struct line *l,
 
 static void load_config(struct global *global)
 {
-       GKeyFile *kf = global->config->keyfile;
+       GKeyFile *kf;
+       
+       kf = global->config->keyfile;
        if (!g_key_file_has_group(kf, "log-irssi")) {
                del_log_filter("log_irssi");
                return;
        }
 
        if (!g_key_file_has_key(kf, "log-irssi", "logfile", NULL)) {
-               logfile = g_build_filename(global->config->config_dir, "log_irssi", NULL);
+               logbasedir = g_build_filename(global->config->config_dir, "log_irssi", NULL);
        } else {
-               logfile = g_key_file_get_string(kf, "log-irssi", "logfile", NULL);
+               logbasedir = g_key_file_get_string(kf, "log-irssi", "logfile", NULL);
        }
        
-       /* Create logfile directory if it doesn't exist yet */
-       g_mkdir(logfile, 0700);
 
+       log_ctx = log_support_init();
+
+       /* Create logfile directory if it doesn't exist yet */
        add_log_filter("log_irssi", log_data, NULL, 1000);
 }
 
 static gboolean init_plugin()
 {
-       files = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)fclose);
        register_load_config_notify(load_config);
        return TRUE;
 }
index 45b5da3fc69ed3fbe1036e94df830b20769a4244..b5871b5acc2d6ba7fed6ee103133ee38fa990d4d 100644 (file)
@@ -60,6 +60,7 @@
 #include "admin.h"
 #include "log.h"
 #include "isupport.h"
+#include "log_support.h"
 
 /**
  * Global information.
index c1aa951a555960359559063c9e232e9a79cc345e..47e4c20334f0b0fabda0da33c634e1cc1b5ec566 100644 (file)
--- a/src/log.c
+++ b/src/log.c
 */
 
 #include "internals.h"
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#include <stdarg.h>
-#include <stdio.h>
 
 static const char *get_date(void)
 {
diff --git a/src/log_support.c b/src/log_support.c
new file mode 100644 (file)
index 0000000..1448202
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+       ctrlproxy: A modular IRC proxy
+       (c) 2002-2007 Jelmer Vernooij <jelmer@nl.linux.org>
+
+       This program 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 2 of the License, or
+       (at your option) any later version.
+
+       This program 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, write to the Free Software
+       Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "internals.h"
+
+#define MAX_OPEN_LOGFILES 300
+
+static void free_file_info(void *_data)
+{
+       struct log_file_info *data = _data;
+
+       fclose(data->file);
+       g_free(data);
+}
+
+struct log_support_context *log_support_init(void)
+{
+       struct log_support_context *ret = g_new0(struct log_support_context, 1);
+
+       ret->files = g_hash_table_new_full(g_str_hash, g_str_equal, 
+                       g_free, free_file_info);
+
+       return ret;
+}
+
+void free_log_support_context(struct log_support_context *ret)
+{
+       g_hash_table_destroy(ret->files);
+       g_free(ret);
+}
+
+#define CLEANUP_THRESHOLD (60 * 60)
+
+static void eval_remove(gpointer key, gpointer value, gpointer user_data)
+{
+       struct log_file_info *fi = value;
+       struct log_support_context *ctx = user_data;
+
+       if (fi->last_used < time(NULL) - CLEANUP_THRESHOLD) {
+               fclose(fi->file);
+               ctx->num_opened--;
+               fi->file = NULL;
+       }
+}
+
+void log_support_cleanup(struct log_support_context *ctx)
+{
+       g_hash_table_foreach(ctx->files, eval_remove, ctx);
+}
+
+gboolean log_support_write(struct log_support_context *ctx, 
+                                          const char *path,
+                                          const char *text)
+{
+       struct log_file_info *fi;
+       
+       /* First, check if the file is still present in the hash table */
+       fi = g_hash_table_lookup(ctx->files, path);
+
+       if (fi == NULL) {
+               fi = g_new0(struct log_file_info, 1);
+               g_hash_table_insert(ctx->files, g_strdup(path), fi);
+       }
+
+       if (fi->file == NULL) {
+               char *dirpath;
+               if (ctx->num_opened > MAX_OPEN_LOGFILES)
+                       log_support_cleanup(ctx);
+
+               dirpath = g_path_get_dirname(path);
+               if (g_mkdir_with_parents(dirpath, 0700) == -1) {
+                       log_global(LOG_ERROR, "Unable to create directory `%s'!", dirpath);
+                       g_free(dirpath);
+                       return FALSE;
+               }
+               g_free(dirpath);
+
+               /* Then open the correct filename */
+               fi->file = fopen(path, "a+");
+               if (fi->file == NULL) {
+                       log_global(LOG_ERROR, "Couldn't open file %s for logging!", path);
+                       return FALSE;
+               }
+
+               ctx->num_opened++;
+       }
+
+       fputs(text, fi->file);
+       fflush(fi->file);
+
+       fi->last_used = time(NULL);
+       return TRUE;
+}
+
+void log_support_writef(struct log_support_context *ctx, 
+                                          const char *path,
+                                          const char *fmt, ...)
+{
+       va_list ap;
+       char *ret;
+       va_start(ap, fmt);
+       ret = g_strdup_vprintf(fmt, ap);
+       log_support_write(ctx, path, ret);
+       va_end(ap);
+}
diff --git a/src/log_support.h b/src/log_support.h
new file mode 100644 (file)
index 0000000..0b2a71e
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+       ctrlproxy: A modular IRC proxy
+       (c) 2002-2007 Jelmer Vernooij <jelmer@nl.linux.org>
+
+       This program 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 2 of the License, or
+       (at your option) any later version.
+
+       This program 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, write to the Free Software
+       Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef _CTRLPROXY_LOG_SUPPORT_H_
+#define _CTRLPROXY_LOG_SUPPORT_H_
+
+#include <stdio.h>
+
+struct log_file_info {
+       FILE *file;
+       time_t last_used;
+};
+
+struct log_support_context {
+       GHashTable *files;
+       int num_opened;
+};
+
+struct log_support_context *log_support_init(void);
+gboolean log_support_write(struct log_support_context *ctx, 
+                                                  const char *path,
+                                                  const char *text);
+void log_support_writef(struct log_support_context *ctx, 
+                                          const char *path,
+                                          const char *fmt, ...);
+void free_log_support_context(struct log_support_context *);
+
+#endif /* _CTRLPROXY_LOG_SUPPORT_H_ */
index 5e860ecb1f924649ebfbe3c77fae42961e29cd8a..8e1c748a03f4dcc177d98f5e922ce593a509888f 100644 (file)
@@ -168,7 +168,7 @@ int main(int argc, char **argv)
        char *logfile = NULL;
        extern enum log_level current_log_level;
        extern gboolean no_log_timestamp;
-       const char *config_dir = NULL;
+       char *config_dir = NULL;
        char *tmp;
        gboolean init = FALSE;
        const char *inetd_client = NULL;
@@ -323,5 +323,7 @@ int main(int argc, char **argv)
 
        g_main_loop_run(main_loop);
 
+       g_free(config_dir);
+
        return 0;
 }
index 9d062f3f60e2b1e04cd57261071baabbbd8c0e29..3d0fc96a1420964609cfe539f9b57c9f35934c6b 100644 (file)
@@ -480,7 +480,7 @@ gboolean network_send_line(struct network *s, struct client *c,
        l = *ol;
 
        if (l.origin == NULL && s->state != NULL) {
-               tmp = l.origin = g_strdup(s->state->me.nick);
+               tmp = l.origin = g_strdup(s->state->me.hostmask);
        }
 
        if (l.origin != NULL) {
@@ -1399,6 +1399,10 @@ void fini_networks(struct global *global)
                disconnect_network(n);
                unload_network(n);
        }
+
+       if (virtual_network_ops != NULL)
+               g_hash_table_destroy(virtual_network_ops);
+       virtual_network_ops = NULL;
 }
 
 /**
index a33848fe01d8e8b7dcbc24285b5d926ccdf3aeed..4a59875f35bf2439e670de97d7fcee2a5855134c 100644 (file)
@@ -820,6 +820,7 @@ void free_config(struct ctrlproxy_config *cfg)
        g_free(cfg->replication);
        g_free(cfg->linestack_backend);
        g_free(cfg->motd_file);
+       g_free(cfg->admin_user);
        g_key_file_free(cfg->keyfile);
        g_free(cfg);
 }