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 | e4b5d37def5023905e98bc0b6c6f81c2d56ba362 (patch) | |
tree | 76dbdd53079e4f05529c002284467820c8d5d0ef | |
parent | 1107c4341552ecb568b43292fc219a73e0d49a0f (diff) | |
download | wydawca-e4b5d37def5023905e98bc0b6c6f81c2d56ba362.tar.gz wydawca-e4b5d37def5023905e98bc0b6c6f81c2d56ba362.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/wydawca/trunk@295 6bb4bd81-ecc2-4fd4-a2d4-9571d19c0d33
-rw-r--r-- | src/Makefile.am | 8 | ||||
-rw-r--r-- | src/config.c | 174 | ||||
-rw-r--r-- | src/diskio.c | 2 | ||||
-rw-r--r-- | src/gpg.c | 1 | ||||
-rw-r--r-- | src/mail.c | 133 | ||||
-rw-r--r-- | src/mail.h | 11 | ||||
-rw-r--r-- | src/method.c | 21 | ||||
-rw-r--r-- | src/process.c | 17 | ||||
-rw-r--r-- | src/sql.c | 22 | ||||
-rw-r--r-- | src/sql.h | 2 | ||||
-rw-r--r-- | src/triplet.c | 8 | ||||
-rw-r--r-- | src/verify.c | 60 | ||||
-rw-r--r-- | src/wydawca.c | 48 | ||||
-rw-r--r-- | src/wydawca.h | 15 | ||||
-rw-r--r-- | src/wydawca.rc | 28 |
15 files changed, 490 insertions, 60 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 26a9a79..7cb4be4 100644 --- a/src/Makefile.am +++ b/src/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/src/config.c b/src/config.c index e5ee832..559e995 100644 --- a/src/config.c +++ b/src/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/src/diskio.c b/src/diskio.c index e4dd56e..fec685c 100644 --- a/src/diskio.c +++ b/src/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, @@ -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/src/mail.c b/src/mail.c new file mode 100644 index 0000000..0f91ebd --- /dev/null +++ b/src/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/src/mail.h b/src/mail.h new file mode 100644 index 0000000..d3710ea --- /dev/null +++ b/src/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/src/method.c b/src/method.c index 45dea5a..114328f 100644 --- a/src/method.c +++ b/src/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/src/process.c b/src/process.c index b7ead65..ad911a7 100644 --- a/src/process.c +++ b/src/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); } @@ -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; } @@ -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/src/triplet.c b/src/triplet.c index f5eebc6..daf3265 100644 --- a/src/triplet.c +++ b/src/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/src/verify.c b/src/verify.c index e63d524..2ccdfaa 100644 --- a/src/verify.c +++ b/src/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/src/wydawca.c b/src/wydawca.c index 398cadd..559970a 100644 --- a/src/wydawca.c +++ b/src/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; } + mail_init (); + logmsg (LOG_NOTICE, "wydawca (%s) started", PACKAGE_STRING); scan_directories (); logmsg (LOG_NOTICE, "wydawca (%s) finished", PACKAGE_STRING); logstats (); + + mail_finish (); + exit (0); } diff --git a/src/wydawca.h b/src/wydawca.h index 4d96ef6..68a8cb7 100644 --- a/src/wydawca.h +++ b/src/wydawca.h @@ -37,6 +37,7 @@ #include "xalloc.h" #include "progname.h" #include "backupfile.h" +#include "inttostr.h" #include "gsc.h" /* The range of directive versions we accept (major * 100 + minor) */ @@ -64,7 +65,7 @@ struct access_method to use; 1 - Request template */ - int init_passed; /* Is the structure initialized */ + int init_passed; /* Initialization count */ char *result; /* Last result string */ size_t result_size; /* Size of result */ union @@ -104,9 +105,9 @@ struct directory_pair char *dest_dir; /* Destination directory */ time_t file_sweep_time; /* Remove invalid/unprocessed files after this amount of time */ - struct access_method verify_method; /* Method for verification user's + struct access_method *verify_method; /* Method for verification user's access to the project */ - struct access_method gpg_key_method; /* Method for retrieving the user + struct access_method *gpg_key_method; /* Method for retrieving the user public key */ struct archive_descr archive; /* Archivation data */ }; @@ -174,12 +175,13 @@ enum wydawca_stat struct kw_expansion { - int kw; + char *kw; char *value; }; char *expand_param (const char *param, const struct kw_expansion *exp, size_t nexp); +void free_kwexp (struct kw_expansion *exp, size_t nexp); /* Global variables */ @@ -204,6 +206,9 @@ extern unsigned long print_stats; } \ while (0) +int stat_mask_p (unsigned long mask); +void make_stat_expansion (struct kw_expansion *exp); + /* Utility functions */ char *safe_file_name (char *file_name); @@ -232,8 +237,10 @@ void scan_directories (void); void register_directory_pair (struct directory_pair *dpair); void register_file (struct file_info *finfo); void enumerate_triplets (struct directory_pair *); +size_t count_collected_triplets (void); /* General-purpose method support */ +struct access_method *method_new (enum access_method_type type); int method_init (struct access_method *method); int method_done (struct access_method *method); int method_run (struct access_method *method, const char *cmd); diff --git a/src/wydawca.rc b/src/wydawca.rc index 16f1a27..77d3af6 100644 --- a/src/wydawca.rc +++ b/src/wydawca.rc @@ -15,6 +15,34 @@ end umask 022 tar-program /bin/tar +admin-addres gray@localhost +from-address wydawca@localhost +mail-admin-stat all + +admin-stat-message +Subject: Wydawca stats + +This is to notify you that the run of wydawca on %{date} +caused the following results: + +errors ............................. %{stat:errors} +warning ............................ %{stat:warnings} +bad signatures ..................... %{stat:bad_signatures} +access violation attempts .......... %{stat:access_violations} +complete triplets .................. %{stat:complete_triplets} +incomplete triplets ................ %{stat:incomplete_triplets} +bad triplets ....................... %{stat:bad_triplets} +expired triplets ................... %{stat:expired_triplets} +triplet successes .................. %{stat:triplet_success} +files uploaded ..................... %{stat:uploads} +files archived ..................... %{stat:archives} +symlinks created ................... %{stat:symlinks} +symlinks removed ................... %{stat:rmsymlinks} + +Regards, +Wydawca +end + directory source /home/ftp/incoming/ftp destination /home/ftp/gnu |