aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2007-08-25 13:29:33 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2007-08-25 13:29:33 +0000
commitda200e0c8611d9c81cd8c76dfffcfa3c61e063ec (patch)
treeddaba33d68d53e81010a489fb20bfc19dd67dac5
parentcb24f7803589330b159660ab0d83a5da447dba74 (diff)
downloadgsc-da200e0c8611d9c81cd8c76dfffcfa3c61e063ec.tar.gz
gsc-da200e0c8611d9c81cd8c76dfffcfa3c61e063ec.tar.bz2
* configure.ac: Require mailutils for wydawca
* bootstrap: Require inttostr and strftime * wydawca/mail.h: New file * wydawca/mail.c: New file * wydawca/Makefile.am: Add mail.c and mail.h * wydawca/wydawca.c: Include mail.h (stat_mask_p, make_stat_expansion): New functions (logstats): Call mail_stats (main): Call initialize mailer subsystem * wydawca/sql.c, wydawca/sql.h: Keep usage reference count. Do not deinitialize unless it falls to 0. Do not initialize if it is > 0. * wydawca/verify.c (expand_param): Rewrite to allow long keywords All callers updated. * wydawca/wydawca.h (struct access_method): Keep reference count (struct directory_pair): verify_method and gpg_key_method are pointers to structs. (struct kw_expansion): kw is char* (count_collected_triplets): New function (method_new): New function * wydawca/config.c: reimplement verify-user and gpg-key New keywords mailer, admin-address, from-address, mail-admin-stat and admin-stat-message * wydawca/process.c: Close methods only when their reference count is 0. * wydawca/method.c: Likewise. (method_new): New function * wydawca/wydawca.rc: Update * wydawca/diskio.c: Minor changes * wydawca/triplet.c (count_collected_triplets): New function * jabberd/main.c: Minor change git-svn-id: file:///svnroot/gsc/trunk@292 d2de0444-eb31-0410-8365-af798a554d48
-rw-r--r--ChangeLog33
-rw-r--r--bootstrap2
-rw-r--r--configure.ac21
-rw-r--r--jabberd/main.c2
-rw-r--r--wydawca/Makefile.am8
-rw-r--r--wydawca/config.c174
-rw-r--r--wydawca/diskio.c2
-rw-r--r--wydawca/gpg.c1
-rw-r--r--wydawca/mail.c133
-rw-r--r--wydawca/mail.h11
-rw-r--r--wydawca/method.c21
-rw-r--r--wydawca/process.c17
-rw-r--r--wydawca/sql.c22
-rw-r--r--wydawca/sql.h2
-rw-r--r--wydawca/triplet.c8
-rw-r--r--wydawca/verify.c60
-rw-r--r--wydawca/wydawca.c48
-rw-r--r--wydawca/wydawca.h15
-rw-r--r--wydawca/wydawca.rc28
19 files changed, 545 insertions, 63 deletions
diff --git a/ChangeLog b/ChangeLog
index c2cd140..71a5ed6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,38 @@
2007-08-25 Sergey Poznyakoff <gray@gnu.org.ua>
+ * configure.ac: Require mailutils for wydawca
+ * bootstrap: Require inttostr and strftime
+ * wydawca/mail.h: New file
+ * wydawca/mail.c: New file
+ * wydawca/Makefile.am: Add mail.c and mail.h
+ * wydawca/wydawca.c: Include mail.h
+ (stat_mask_p, make_stat_expansion): New functions
+ (logstats): Call mail_stats
+ (main): Call initialize mailer subsystem
+
+ * wydawca/sql.c, wydawca/sql.h: Keep usage reference count. Do not
+ deinitialize unless it falls to 0. Do not initialize if it is > 0.
+
+ * wydawca/verify.c (expand_param): Rewrite to allow long keywords
+ All callers updated.
+ * wydawca/wydawca.h (struct access_method): Keep reference count
+ (struct directory_pair): verify_method and gpg_key_method are
+ pointers to structs.
+ (struct kw_expansion): kw is char*
+ (count_collected_triplets): New function
+ (method_new): New function
+ * wydawca/config.c: reimplement verify-user and gpg-key
+ New keywords mailer, admin-address, from-address, mail-admin-stat
+ and admin-stat-message
+ * wydawca/process.c: Close methods only when their reference count
+ is 0.
+ * wydawca/method.c: Likewise.
+ (method_new): New function
+ * wydawca/wydawca.rc: Update
+ * wydawca/diskio.c: Minor changes
+ * wydawca/triplet.c (count_collected_triplets): New function
+ * jabberd/main.c: Minor change
+
* wydawca/wydawca.c, wydawca/config.c, wydawca/gpg.c: New stat
types STAT_ACCESS_VIOLATIONS and STAT_BAD_SIGNATURES.
* wydawca/wydawca.h (expand_param): New function
diff --git a/bootstrap b/bootstrap
index 124bda4..ba6a6c8 100644
--- a/bootstrap
+++ b/bootstrap
@@ -43,5 +43,5 @@ test -d m4 || mkdir m4 || exit 1
test -d gnu || mkdir gnu || exit 1
gnulib-tool --source-base=gnu --import \
xalloc obstack getopt hash error progname getline mkdtemp save-cwd \
- backupfile strerror vasprintf &&
+ backupfile strerror vasprintf inttostr strftime &&
autoreconf -f -i -s
diff --git a/configure.ac b/configure.ac
index ebeb7c3..8654356 100644
--- a/configure.ac
+++ b/configure.ac
@@ -171,13 +171,32 @@ fi])
need_mysql=no
need_gpgme=no
-
+need_mailutils=no
+
GSC_MODULE_ENABLE(wydawca,[
need_mysql=yes
need_gpgme=yes
+ need_mailutils=yes
])
# **********************
+# Mailutils
+# **********************
+status_mailutils=no
+
+AC_PATH_PROG(MU_CONFIG, mailutils-config, none, $PATH)
+if test "$MU_CONFIG" != "none"; then
+ status_mailutils=yes
+ AC_SUBST(MAILUTILS_VERSION, `$MU_CONFIG --info version|sed s/.*=//`)
+ AC_SUBST(MAILUTILS_INCLUDES, `$MU_CONFIG --compile`)
+ AC_SUBST(MAILUTILS_LIBS, `$MU_CONFIG --link mailer`)
+else
+ if test "$need_mailutils" = "yes"; then
+ AC_MSG_FAILURE([The requested library libmailutils is not found])
+ fi
+fi
+
+# **********************
# MySQL
# **********************
status_mysql=no
diff --git a/jabberd/main.c b/jabberd/main.c
index cc229fb..de0551f 100644
--- a/jabberd/main.c
+++ b/jabberd/main.c
@@ -797,7 +797,7 @@ main(int argc, char **argv)
exit (1);
}
- parse_config();
+ parse_config ();
if (!log_to_stderr)
{
diff --git a/wydawca/Makefile.am b/wydawca/Makefile.am
index 26a9a79..7cb4be4 100644
--- a/wydawca/Makefile.am
+++ b/wydawca/Makefile.am
@@ -29,8 +29,10 @@ wydawca_SOURCES=\
triplet.c\
verify.c\
wydawca.c\
- wydawca.h
+ wydawca.h\
+ mail.h\
+ mail.c
-LDADD=../lib/libgsc.a ../gnu/libgnu.a @SQLLIB@ @GPGMELIB@
-INCLUDES = -I$(top_srcdir)/lib -I$(top_srcdir)/gnu -I../gnu
+LDADD=../lib/libgsc.a ../gnu/libgnu.a @SQLLIB@ @GPGMELIB@ @MAILUTILS_LIBS@
+INCLUDES = -I$(top_srcdir)/lib -I$(top_srcdir)/gnu -I../gnu @MAILUTILS_INCLUDES@
AM_CPPFLAGS=-DSYSCONFDIR=\"$(sysconfdir)\"
diff --git a/wydawca/config.c b/wydawca/config.c
index e5ee832..559e995 100644
--- a/wydawca/config.c
+++ b/wydawca/config.c
@@ -17,9 +17,14 @@
#include "wydawca.h"
#include "sql.h"
#include "argmatch.h"
+#include <mail.h>
+#define obstack_chunk_alloc malloc
+#define obstack_chunk_free free
+#include "obstack.h"
/* Configuration file handling (application-specific) */
+static struct obstack cfg_stk;
static struct access_method default_verify_method;
static struct access_method default_gpg_key_method;
static struct archive_descr default_archive_descr;
@@ -293,16 +298,25 @@ static void
cfg_verify_user (gsc_config_file_t *file, char *kw, char *val, void *data)
{
struct directory_pair *dp = data;
- _cfg_access_method (file, kw, val,
- dp ? &dp->verify_method : &default_verify_method);
+ struct access_method *method;
+ if (dp)
+ method = dp->verify_method = method_new (method_builtin);
+ else
+ method = &default_verify_method;
+
+ _cfg_access_method (file, kw, val, method);
}
static void
cfg_gpg_key (gsc_config_file_t *file, char *kw, char *val, void *data)
{
struct directory_pair *dp = data;
- _cfg_access_method (file, kw, val,
- dp ? &dp->gpg_key_method : &default_gpg_key_method);
+ struct access_method *method;
+ if (dp)
+ method = dp->gpg_key_method = method_new (method_builtin);
+ else
+ method = &default_gpg_key_method;
+ _cfg_access_method (file, kw, val, method);
}
static char const * const backup_args[] =
@@ -450,8 +464,8 @@ cfg_directory (gsc_config_file_t *file, char *kw, char *val, void *unused)
memset (&dpair, 0, sizeof dpair);
dpair.file_sweep_time = file_sweep_time;
- dpair.verify_method = default_verify_method;
- dpair.gpg_key_method = default_gpg_key_method;
+ dpair.verify_method = &default_verify_method;
+ dpair.gpg_key_method = &default_gpg_key_method;
dpair.archive = default_archive_descr;
gsc_config_parse_block (file, &dpair, keywords, "end");
@@ -480,19 +494,19 @@ cfg_directory (gsc_config_file_t *file, char *kw, char *val, void *unused)
dpair.dest_dir);
file->error_count++;
}
- else if (dpair.verify_method.type != method_none
- && dpair.gpg_key_method.type != method_none)
+ else if (dpair.verify_method->type != method_none
+ && dpair.gpg_key_method->type != method_none)
{
/* FIXME: only sql supported so far */
- if (dpair.verify_method.type == method_builtin
- && dpair.gpg_key_method.type != method_builtin)
+ if (dpair.verify_method->type == method_builtin
+ && dpair.gpg_key_method->type != method_builtin)
{
file->error_msg (file->file_name, file->line,
"Sorry, method `builtin' is not yet supported");
file->error_count++;
}
- else if (dpair.verify_method.type == method_external
- && dpair.gpg_key_method.type != method_external)
+ else if (dpair.verify_method->type == method_external
+ && dpair.gpg_key_method->type != method_external)
{
file->error_msg (file->file_name, file->line,
"Sorry, method `external' is not yet supported");
@@ -661,12 +675,13 @@ static unsigned long stat_types[] = {
ARGMATCH_VERIFY (stat_args, stat_types);
static void
-cfg_statistics (gsc_config_file_t *file, char *kw, char *val, void *unused)
+_cfg_statmask (gsc_config_file_t *file, char *val, unsigned long *pmask)
{
int i;
int argc;
char **argv;
int invert = 0;
+ unsigned long mask;
if (argcv_get (val, NULL, NULL, &argc, &argv))
{
@@ -679,17 +694,17 @@ cfg_statistics (gsc_config_file_t *file, char *kw, char *val, void *unused)
i = 0;
if (strcmp (argv[0], "all") == 0)
{
- print_stats = STAT_MASK_ALL;
+ mask = STAT_MASK_ALL;
invert = 1;
i++;
}
else if (strcmp (val, "none") == 0)
{
- print_stats = STAT_MASK_NONE;
+ mask = STAT_MASK_NONE;
i++;
}
else
- print_stats = STAT_MASK_NONE;
+ mask = STAT_MASK_NONE;
for (; i < argc; i++)
{
@@ -703,12 +718,119 @@ cfg_statistics (gsc_config_file_t *file, char *kw, char *val, void *unused)
return;
}
if (invert)
- print_stats &= ~ STAT_MASK (stat_types[x]);
+ mask &= ~ STAT_MASK (stat_types[x]);
else
- print_stats |= STAT_MASK (stat_types[x]);
+ mask |= STAT_MASK (stat_types[x]);
}
+ *pmask = mask;
+}
+
+static void
+cfg_statistics (gsc_config_file_t *file, char *kw, char *val, void *unused)
+{
+ _cfg_statmask (file, val, &print_stats);
}
+
+static void
+_cfg_email (gsc_config_file_t *file, char *kw, char *val, mu_address_t *paddr)
+{
+ mu_address_t addr;
+ int rc = mu_address_create (&addr, val);
+ if (rc)
+ {
+ file->error_msg (file->file_name, file->line,
+ "invalid mail address: %s", mu_strerror (rc));
+ file->error_count++;
+ }
+ *paddr = addr;
+}
+
+static void
+cfg_mailer (gsc_config_file_t *file, char *kw, char *val, void *unused)
+{
+ int rc = mu_mailer_create (&mailer, val);
+ if (rc)
+ {
+ file->error_msg (file->file_name, file->line,
+ "creating mailer `%s' failed: %s",
+ val, mu_strerror (rc));
+ file->error_count++;
+ }
+}
+
+static void
+cfg_admin_address (gsc_config_file_t *file, char *kw, char *val, void *unused)
+{
+ _cfg_email (file, kw, val, &admin_address);
+}
+
+static void
+cfg_from_address (gsc_config_file_t *file, char *kw, char *val, void *unused)
+{
+ _cfg_email (file, kw, val, &from_address);
+}
+
+static void
+cfg_mail_admin_stat (gsc_config_file_t *file, char *kw, char *val,
+ void *unused)
+{
+ _cfg_statmask (file, val, &mail_admin_mask);
+}
+
+static int
+end_marker_p (const char *buf, const char *word, size_t wlen)
+{
+ if (strlen (buf) >= wlen && memcmp (buf, word, wlen) == 0)
+ {
+ while (buf[wlen] && isspace (buf[wlen]))
+ wlen++;
+ if (buf[wlen] == 0 || buf[wlen] == '#')
+ return 1;
+ }
+ return 0;
+}
+
+static int
+_cfg_raw_read (gsc_config_file_t *file, char *val, struct obstack *stk)
+{
+ size_t size = 0;
+ char *buf = NULL;
+ char *word = val ? get_word (&val) : "";
+ size_t wlen;
+ size_t start_line = file->line;
+
+ if (word[0] == 0)
+ word = "end";
+ wlen = strlen (word);
+
+ while (getline (&buf, &size, file->fp) > 0)
+ {
+ file->line++;
+ if (end_marker_p (buf, word, wlen))
+ {
+ obstack_1grow (stk, 0);
+ free (buf);
+ return 0;
+ }
+ obstack_grow (stk, buf, strlen (buf));
+ }
+
+ file->error_msg (file->file_name, start_line, "missing end marker");
+ file->error_count++;
+ return 1;
+}
+
+static void
+cfg_admin_stat_message (gsc_config_file_t *file, char *kw, char *val,
+ void *unused)
+{
+ if (_cfg_raw_read (file, val, &cfg_stk) == 0)
+ admin_stat_message_template = obstack_finish (&cfg_stk);
+}
+
+
+
static struct gsc_config_keyword kw_handler[] = {
{ "syslog-tag", cfg_syslog_tag },
{ "syslog-facility", cfg_syslog_facility },
@@ -722,6 +844,11 @@ static struct gsc_config_keyword kw_handler[] = {
{ "umask", cfg_umask },
{ "tar-program", cfg_tar_program },
{ "archive", cfg_archive },
+ { "mailer", cfg_mailer },
+ { "admin-addres", cfg_admin_address },
+ { "from-address", cfg_from_address },
+ { "mail-admin-stat", cfg_mail_admin_stat },
+ { "admin-stat-message", cfg_admin_stat_message },
{ NULL }
};
@@ -732,10 +859,19 @@ parse_config ()
default_gpg_key_method.type = method_builtin;
default_archive_descr.type = archive_none;
default_archive_descr.backup_type = no_backups;
-
+
+ obstack_init (&cfg_stk);
switch (gsc_config_parse (conffile, NULL, kw_handler))
{
case gsc_config_success:
+ if (mail_admin_mask)
+ {
+ if (!admin_stat_message_template)
+ error (1, 0,
+ "mail-admin-stat given, but not admin-stat-message");
+ if (!admin_address)
+ error (1, 0, "mail-admin-stat given, but not admin-address");
+ }
break;
case gsc_config_open:
diff --git a/wydawca/diskio.c b/wydawca/diskio.c
index e4dd56e..fec685c 100644
--- a/wydawca/diskio.c
+++ b/wydawca/diskio.c
@@ -286,7 +286,6 @@ do_move_file (const char *file, const char *dst_file, uid_t uid, gid_t gid)
int
tar_append_file (const char *archive, const char *file)
{
- int rc;
const char *argv[6];
if (debug_level)
@@ -515,7 +514,6 @@ symlink_file (struct file_triplet *trp, struct directory_pair *dpair,
const char *reldir,
const char *wanted_src, const char *wanted_dst)
{
- char *dst_file;
int rc = 0;
struct saved_cwd cwd;
char *dst_dir = create_directory (dpair->dest_dir, reldir,
diff --git a/wydawca/gpg.c b/wydawca/gpg.c
index e014e14..3372c7b 100644
--- a/wydawca/gpg.c
+++ b/wydawca/gpg.c
@@ -223,7 +223,6 @@ verify_directive_signature (struct file_triplet *trp,
if (ec == GPG_ERR_NO_ERROR)
{
gpgme_verify_result_t result;
- gpgme_signature_t sig;
result = gpgme_op_verify_result (ctx);
if (gpg_sig_ok_p (ctx, result->signatures))
diff --git a/wydawca/mail.c b/wydawca/mail.c
new file mode 100644
index 0000000..0f91ebd
--- /dev/null
+++ b/wydawca/mail.c
@@ -0,0 +1,133 @@
+/* wydawca - FTP release synchronization daemon
+ Copyright (C) 2007 Sergey Poznyakoff
+
+ 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 3 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, see <http://www.gnu.org/licenses/>. */
+
+#include "wydawca.h"
+#include <mail.h>
+
+int mailer_opened;
+mu_mailer_t mailer;
+mu_address_t admin_address;
+mu_address_t from_address;
+unsigned long mail_admin_mask;
+char *admin_stat_message_template;
+
+void
+mail_init ()
+{
+ if (!mailer)
+ {
+ int rc;
+ if ((rc = mu_mailer_create (&mailer, NULL)))
+ {
+ const char *url = NULL;
+ mu_mailer_get_url_default (&url);
+ logmsg (LOG_ERR, "cannot create default mailer `%s': %s",
+ url, mu_strerror (rc));
+ }
+ }
+}
+
+void
+mail_send_message (mu_address_t rcpt, const char *text)
+{
+ int rc;
+ mu_message_t msg;
+ mu_stream_t stream = NULL;
+ mu_header_t hdr;
+ int mailer_flags = 0;
+ static char *x_mailer = "wydawca (" PACKAGE_STRING ")";
+
+ mu_message_create (&msg, NULL);
+
+ mu_message_get_stream (msg, &stream);
+ mu_stream_write (stream, text, strlen (text), 0, NULL);
+ mu_message_get_header (msg, &hdr);
+ mu_header_append (hdr, "X-Mailer", x_mailer);
+
+ if (debug_level > 1)
+ {
+ mu_debug_t debug;
+ mu_mailer_get_debug (mailer, &debug);
+ mu_debug_set_level (debug, MU_DEBUG_TRACE | MU_DEBUG_PROT);
+ if (debug_level > 2)
+ mailer_flags = MAILER_FLAG_DEBUG_DATA;
+ }
+
+ if (!mailer_opened)
+ {
+ if ((rc = mu_mailer_open (mailer, mailer_flags)))
+ {
+ const char *url = NULL;
+ mu_mailer_get_url_default (&url);
+ logmsg (LOG_CRIT, "opening mailer `%s' failed: %s",
+ url, mu_strerror (rc));
+ return;
+ }
+ mailer_opened = 1;
+ }
+
+ rc = mu_mailer_send_message (mailer, msg, from_address, rcpt);
+ if (rc)
+ logmsg (LOG_CRIT, "cannot send message: %s", mu_strerror (rc));
+
+ mu_message_destroy (&msg, mu_message_get_owner (msg));
+}
+
+void
+mail_stats ()
+{
+ struct kw_expansion exp[MAX_STAT + 1];
+ time_t t;
+ char *text;
+
+ if (!stat_mask_p (mail_admin_mask) || !mailer)
+ return;
+
+ if (debug_level)
+ {
+ size_t size;
+ char *buf;
+ mu_address_to_string (admin_address, NULL, 0, &size);
+ buf = xmalloc (size + 1);
+ mu_address_to_string (admin_address, buf, size + 1, NULL);
+ logmsg (LOG_DEBUG, "Sending stats to %s", buf);
+ free (buf);
+ }
+
+ if (dry_run_mode)
+ return;
+
+ time (&t);
+ exp[0].kw = "date";
+ exp[0].value = xstrdup (ctime (&t));
+ exp[0].value [strlen (exp[0].value) - 1] = 0;
+ make_stat_expansion (exp + 1);
+
+ text = expand_param (admin_stat_message_template,
+ exp, sizeof (exp) / sizeof (exp[0]));
+
+ mail_send_message (admin_address, text);
+
+ free (text);
+ free_kwexp (exp, sizeof (exp) / sizeof (exp[0]));
+}
+
+void
+mail_finish ()
+{
+ if (mailer_opened)
+ mu_mailer_close (mailer);
+}
diff --git a/wydawca/mail.h b/wydawca/mail.h
new file mode 100644
index 0000000..d3710ea
--- /dev/null
+++ b/wydawca/mail.h
@@ -0,0 +1,11 @@
+#include <mailutils/mailutils.h>
+
+extern mu_mailer_t mailer;
+extern mu_address_t admin_address;
+extern mu_address_t from_address;
+extern unsigned long mail_admin_mask;
+extern char *admin_stat_message_template;
+
+void mail_init (void);
+void mail_finish (void);
+void mail_stats (void);
diff --git a/wydawca/method.c b/wydawca/method.c
index 45dea5a..114328f 100644
--- a/wydawca/method.c
+++ b/wydawca/method.c
@@ -32,18 +32,27 @@ static struct method_descr method_tab[] = {
{ "external", NULL, NULL, NULL }
};
+struct access_method *
+method_new (enum access_method_type type)
+{
+ struct access_method *mp = xmalloc (sizeof mp[0]);
+ memset (mp, 0, sizeof mp[0]);
+ mp->type = type;
+ return mp;
+}
+
int
method_init (struct access_method *method)
{
struct method_descr *mp = method_tab + method->type;
int rc = 0;
+ if (method->init_passed++)
+ return 0;
if (debug_level > 1)
logmsg (LOG_DEBUG, "Initializing method: %s \"%s\" \"%s\"",
mp->name, method->param[0],
method->param[1] ? method->param[1] : "");
- if (method->init_passed)
- return 0;
if (mp->init)
rc = mp->init (method);
if (rc == 0)
@@ -57,19 +66,19 @@ method_done (struct access_method *method)
struct method_descr *mp = method_tab + method->type;
int rc = 0;
+ if (method->init_passed == 0)
+ return 0;
+ if (--method->init_passed)
+ return 0;
if (debug_level > 1)
logmsg (LOG_DEBUG, "Closing method: %s \"%s\" \"%s\"",
mp->name, method->param[0],
method->param[1] ? method->param[1] : "");
- if (!method->init_passed)
- return 0;
if (mp->done)
rc = mp->done (method);
free (method->result);
method->result = NULL;
method->result_size = 0;
- if (rc == 0)
- method->init_passed = 0;
return rc;
}
diff --git a/wydawca/process.c b/wydawca/process.c
index b7ead65..ad911a7 100644
--- a/wydawca/process.c
+++ b/wydawca/process.c
@@ -64,6 +64,7 @@ file_type_str (enum file_type type)
case file_directive:
return "signed upload directive";
}
+ return "UNKNOWN";
}
#define SUF_SIG ".sig"
@@ -168,12 +169,17 @@ scan_directory_pair (struct directory_pair *dpair)
closedir (dir);
- if (method_init (&dpair->verify_method) == 0
- && method_init (&dpair->gpg_key_method) == 0)
+ if (count_collected_triplets () > 0
+ && method_init (dpair->verify_method) == 0
+ && method_init (dpair->gpg_key_method) == 0)
enumerate_triplets (dpair);
+}
- method_done (&dpair->verify_method);
- method_done (&dpair->gpg_key_method);
+static void
+close_methods (struct directory_pair *dpair)
+{
+ method_done (dpair->verify_method);
+ method_done (dpair->gpg_key_method);
}
/* Scan all configured update directories */
@@ -183,5 +189,8 @@ scan_directories ()
struct directory_list *dp;
for (dp = dlist; dp; dp = dp->next)
scan_directory_pair (&dp->pair);
+
+ for (dp = dlist; dp; dp = dp->next)
+ close_methods (&dp->pair);
}
diff --git a/wydawca/sql.c b/wydawca/sql.c
index 95c601a..c1de81d 100644
--- a/wydawca/sql.c
+++ b/wydawca/sql.c
@@ -67,14 +67,17 @@ sql_init_method (struct access_method *method)
abort ();
}
- mysql_init (&conn->mysql);
- if (!mysql_real_connect (&conn->mysql, conn->host, conn->user,
- conn->password, conn->database, conn->port,
- conn->socket, 0))
+ if (conn->initcount++ == 0)
{
- logmsg (LOG_ERR, "Failed to connect to database %s: Error: %s\n",
- method->param[0], mysql_error (&conn->mysql));
- return 1;
+ mysql_init (&conn->mysql);
+ if (!mysql_real_connect (&conn->mysql, conn->host, conn->user,
+ conn->password, conn->database, conn->port,
+ conn->socket, 0))
+ {
+ logmsg (LOG_ERR, "Failed to connect to database %s: Error: %s\n",
+ method->param[0], mysql_error (&conn->mysql));
+ return 1;
+ }
}
method->v.sqlconn = conn;
return 0;
@@ -84,6 +87,11 @@ sql_init_method (struct access_method *method)
int
sql_done_method (struct access_method *method)
{
+ struct sqlconn *conn = method->v.sqlconn;
+ if (!conn || conn->initcount == 0)
+ return 0;
+ if (--conn->initcount)
+ return 0;
mysql_close (&method->v.sqlconn->mysql);
return 0;
}
diff --git a/wydawca/sql.h b/wydawca/sql.h
index d3b83d1..6b2e6c4 100644
--- a/wydawca/sql.h
+++ b/wydawca/sql.h
@@ -25,7 +25,7 @@ struct sqlconn
char *database;
char *user;
char *password;
- int init;
+ size_t initcount; /* Number of initializations */
MYSQL mysql;
};
diff --git a/wydawca/triplet.c b/wydawca/triplet.c
index f5eebc6..daf3265 100644
--- a/wydawca/triplet.c
+++ b/wydawca/triplet.c
@@ -106,7 +106,6 @@ triplet_expired_p (struct file_triplet *trp, time_t ttl)
return false;
}
-
enum triplet_state
{
triplet_directive, /* Short triplet: only a directive is present,
@@ -228,3 +227,10 @@ enumerate_triplets (struct directory_pair *dpair)
hash_clear (triplet_table);
}
}
+
+size_t
+count_collected_triplets ()
+{
+ return triplet_table ? hash_get_n_entries (triplet_table) : 0;
+}
+
diff --git a/wydawca/verify.c b/wydawca/verify.c
index e63d524..2ccdfaa 100644
--- a/wydawca/verify.c
+++ b/wydawca/verify.c
@@ -39,16 +39,26 @@ trim (char *str)
}
static const char *
-find_expansion (int c, const struct kw_expansion *exp, size_t nexp)
+find_expansion_char (int c, const struct kw_expansion *exp, size_t nexp)
{
for (; nexp; nexp--, exp++)
- if (exp->kw == c)
+ if (exp->kw[1] == 0 && exp->kw[0] == c)
return exp->value;
return NULL;
}
-/* Expand PARAM by replacing %X with the values as per expansion map EXP
- (of NEXP elements).
+static const char *
+find_expansion_word (char *kw, size_t len,
+ const struct kw_expansion *exp, size_t nexp)
+{
+ for (; nexp; nexp--, exp++)
+ if (strlen (exp->kw) == len && memcmp (exp->kw, kw, len) == 0)
+ return exp->value;
+ return NULL;
+}
+
+/* Expand PARAM by replacing %u with the quoted value of USER, %p with that
+ of PROJECT and %% with a single %. Return the malloc'ed result.
FIXME: Should we quote PARAM itself?
*/
char *
@@ -71,7 +81,18 @@ expand_param (const char *param, const struct kw_expansion *exp, size_t nexp)
len++;
p += 2;
}
- else if ((s = find_expansion (p[1], exp, nexp)) != NULL)
+ else if (p[1] == '{')
+ {
+ char *e = strchr (p + 2, '}');
+ if (e && (s = find_expansion_word (p + 2, e - p - 2, exp, nexp)))
+ {
+ len += strlen (s);
+ p = e + 1;
+ }
+ else
+ len++, p++;
+ }
+ else if ((s = find_expansion_char (p[1], exp, nexp)) != NULL)
{
len += strlen (s);
p += 2;
@@ -102,8 +123,23 @@ expand_param (const char *param, const struct kw_expansion *exp, size_t nexp)
*q++ = *p++;
break;
+ case '{':
+ {
+ char *e = strchr (p + 1, '}');
+ if (e
+ && (s = find_expansion_word (p + 1, e - p - 1, exp, nexp)))
+ {
+ strcpy (q, s);
+ q += strlen (s);
+ p = e + 1;
+ }
+ else
+ len++, p++;
+ }
+ break;
+
default:
- if ((s = find_expansion (*p, exp, nexp)) != NULL)
+ if ((s = find_expansion_char (*p, exp, nexp)) != NULL)
{
strcpy (q, s);
q += strlen (s);
@@ -168,7 +204,7 @@ escape_kwexp (struct access_method *method, struct kw_expansion *exp,
quote_string (method, exp[i].value, &exp[i].value);
}
-static void
+void
free_kwexp (struct kw_expansion *exp, size_t nexp)
{
size_t i;
@@ -185,7 +221,7 @@ int
check_access_rights (struct file_triplet *trp, struct directory_pair *dpair,
const char *user)
{
- struct access_method *method = &dpair->verify_method;
+ struct access_method *method = dpair->verify_method;
char *project;
const char *directory;
char *p;
@@ -215,9 +251,9 @@ check_access_rights (struct file_triplet *trp, struct directory_pair *dpair,
logmsg (LOG_DEBUG, "verifying access rights for user %s to project %s",
user, project);
- kwexp[0].kw = 'u';
+ kwexp[0].kw = "u";
kwexp[0].value = (char*) user;
- kwexp[1].kw = 'p';
+ kwexp[1].kw = "p";
kwexp[1].value = project;
escape_kwexp (method, kwexp, 2);
@@ -255,7 +291,7 @@ verify_directive_file (struct file_triplet *trp, struct directory_pair *dpair)
struct passwd *pw;
char *user_name;
char *command;
- struct access_method *method = &dpair->gpg_key_method;
+ struct access_method *method = dpair->gpg_key_method;
const char *pubkey;
int rc;
struct kw_expansion kwexp[1];
@@ -273,7 +309,7 @@ verify_directive_file (struct file_triplet *trp, struct directory_pair *dpair)
trp->gid = pw->pw_gid;
user_name = pw->pw_name;
- kwexp[0].kw = 'u';
+ kwexp[0].kw = "u";
kwexp[0].value = user_name;
escape_kwexp (method, kwexp, 1);
command = expand_param (method->param[1], kwexp, 1);
diff --git a/wydawca/wydawca.c b/wydawca/wydawca.c
index 398cadd..559970a 100644
--- a/wydawca/wydawca.c
+++ b/wydawca/wydawca.c
@@ -15,6 +15,7 @@
with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "wydawca.h"
+#include "mail.h"
char *conffile = SYSCONFDIR "/wydawca.rc" ;
int debug_level;
@@ -165,6 +166,45 @@ static char *stat_name[MAX_STAT] = {
"symlinks removed",
};
+static char *stat_kwname[MAX_STAT] = {
+ "stat:errors",
+ "stat:warnings",
+ "stat:bad_signatures",
+ "stat:access_violations",
+ "stat:complete_triplets",
+ "stat:incomplete_triplets",
+ "stat:bad_triplets",
+ "stat:expired_triplets",
+ "stat:triplet_success",
+ "stat:uploads",
+ "stat:archives",
+ "stat:symlinks",
+ "stat:rmsymlinks",
+};
+
+int
+stat_mask_p (unsigned long mask)
+{
+ int i;
+
+ for (i = 0; i < MAX_STAT; i++)
+ if (wydawca_stat[i] != 0 && (mask && STAT_MASK (i)))
+ return 1;
+ return 0;
+}
+
+void
+make_stat_expansion (struct kw_expansion *exp)
+{
+ int i;
+ char sbuf[INT_BUFSIZE_BOUND (wydawca_stat[0])];
+ for (i = 0; i < MAX_STAT; i++)
+ {
+ exp[i].kw = stat_kwname[i];
+ exp[i].value = xstrdup (uinttostr (wydawca_stat[i], sbuf));
+ }
+}
+
void
logstats ()
{
@@ -173,6 +213,8 @@ logstats ()
for (i = 0; i < MAX_STAT; i++)
if (print_stats & STAT_MASK (i))
logmsg (LOG_INFO, "%s: %u", stat_name[i], wydawca_stat[i]);
+
+ mail_stats ();
}
@@ -184,6 +226,7 @@ main (int argc, char **argv)
int lint_mode = 0;
program_name = argv[0];
+ mu_register_all_mailer_formats ();
while ((c = getopt_long (argc, argv, "c:dehntv", options, NULL)) != EOF)
{
switch (c)
@@ -244,10 +287,15 @@ main (int argc, char **argv)
log_printer = syslog_printer;</