diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2007-08-25 13:29:33 +0000 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2007-08-25 13:29:33 +0000 |
commit | da200e0c8611d9c81cd8c76dfffcfa3c61e063ec (patch) | |
tree | ddaba33d68d53e81010a489fb20bfc19dd67dac5 | |
parent | cb24f7803589330b159660ab0d83a5da447dba74 (diff) | |
download | gsc-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-- | ChangeLog | 33 | ||||
-rw-r--r-- | bootstrap | 2 | ||||
-rw-r--r-- | configure.ac | 21 | ||||
-rw-r--r-- | jabberd/main.c | 2 | ||||
-rw-r--r-- | wydawca/Makefile.am | 8 | ||||
-rw-r--r-- | wydawca/config.c | 174 | ||||
-rw-r--r-- | wydawca/diskio.c | 2 | ||||
-rw-r--r-- | wydawca/gpg.c | 1 | ||||
-rw-r--r-- | wydawca/mail.c | 133 | ||||
-rw-r--r-- | wydawca/mail.h | 11 | ||||
-rw-r--r-- | wydawca/method.c | 21 | ||||
-rw-r--r-- | wydawca/process.c | 17 | ||||
-rw-r--r-- | wydawca/sql.c | 22 | ||||
-rw-r--r-- | wydawca/sql.h | 2 | ||||
-rw-r--r-- | wydawca/triplet.c | 8 | ||||
-rw-r--r-- | wydawca/verify.c | 60 | ||||
-rw-r--r-- | wydawca/wydawca.c | 48 | ||||
-rw-r--r-- | wydawca/wydawca.h | 15 | ||||
-rw-r--r-- | wydawca/wydawca.rc | 28 |
19 files changed, 545 insertions, 63 deletions
@@ -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 @@ -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; |