From 4213ec5ef9695aa504938c0e764ba9a4f08921b2 Mon Sep 17 00:00:00 2001 From: Sergey Poznyakoff Date: Tue, 24 Feb 2009 00:49:40 +0200 Subject: Initial implementation of daemon mode. * gconf/gconf-gram.y (string_to_sockaddr_: Take struct gconf_sockaddr as the first argument. * gconf/gconf.h (struct gconf_sockaddr): New data type. * src/job.c, src/net.c, src/pidfile.c: New files. * src/Makefile.am (wydawca_SOURCES): Add job.c, net.c, pidfile.c * src/cmdline.opt: New options: --cron (change semantics), --force, --foreground, --single-process, --spool * src/wydawca.c: New daemon mode. * src/config.c: New statements: spool.alias, daemon, foreground, single-process, wakeup-interval, pidfile, listen * src/directive.c, src/diskio.c, src/gpg.c, src/mail.c, src/null.c, src/process.c, src/triplet.c, src/verify.c, src/vtab.c, src/wydawca.h: use static struct spool wherever feasible. * src/triplet.c: New meta-variable "spool" * tests/etc/wydawca.rcin: Update. * tests/upload-dry.at: Update. --- gconf/gconf-gram.y | 20 ++-- gconf/gconf.h | 5 + src/Makefile.am | 4 + src/cmdline.opt | 48 +++++++-- src/config.c | 40 ++++--- src/directive.c | 2 +- src/diskio.c | 14 +-- src/gpg.c | 4 +- src/job.c | 278 +++++++++++++++++++++++++++++++++++++++++++++++++ src/mail.c | 15 +-- src/net.c | 227 ++++++++++++++++++++++++++++++++++++++++ src/null.c | 22 ++-- src/pidfile.c | 90 ++++++++++++++++ src/process.c | 66 ++++++++++-- src/triplet.c | 18 +++- src/verify.c | 4 +- src/vtab.c | 8 +- src/wydawca.c | 112 ++++++++++---------- src/wydawca.h | 83 ++++++++++----- tests/etc/wydawca.rcin | 3 +- tests/mailstats.at | 2 +- tests/notify-upl.at | 2 +- tests/upload-dry.at | 10 +- tests/upload.at | 2 +- 24 files changed, 913 insertions(+), 166 deletions(-) create mode 100644 src/job.c create mode 100644 src/net.c create mode 100644 src/pidfile.c diff --git a/gconf/gconf-gram.y b/gconf/gconf-gram.y index a1d9f2a..f7ee710 100644 --- a/gconf/gconf-gram.y +++ b/gconf/gconf-gram.y @@ -506,19 +506,23 @@ string_to_host (struct in_addr *in, const char *string) } static int -string_to_sockaddr (sockaddr_union_t *s, const char *string) +string_to_sockaddr (struct gconf_sockaddr *sp, const char *string) { if (string[0] == '/') { - if (strlen (string) >= sizeof (s->s_un.sun_path)) + struct sockaddr_un s_un; + if (strlen (string) >= sizeof (s_un.sun_path)) { gconf_error (&gconf_current_locus, 0, _("%s: UNIX socket name too long"), string); return 1; } - s->s_un.sun_family = AF_UNIX; - strcpy (s->s_un.sun_path, string); + s_un.sun_family = AF_UNIX; + strcpy (s_un.sun_path, string); + sp->len = sizeof (s_un); + sp->sa = xmalloc (sp->len); + memcpy (sp->sa, &s_un, sp->len); } else { @@ -583,7 +587,9 @@ string_to_sockaddr (sockaddr_union_t *s, const char *string) gconf_error (&gconf_current_locus, 0, _("missing port number")); return 1; } - s->s_in = sa; + sp->len = sizeof (sa); + sp->sa = xmalloc (sp->len); + memcpy (sp->sa, &sa, sp->len); } return 0; } @@ -689,7 +695,7 @@ string_convert (void *target, enum gconf_data_type type, const char *string) break; case gconf_type_sockaddr: - return string_to_sockaddr ((sockaddr_union_t*)target, string); + return string_to_sockaddr ((struct gconf_sockaddr *)target, string); /* FIXME: */ case gconf_type_cidr: @@ -720,7 +726,7 @@ size_t gconf_type_size_tab[] = { sizeof (struct in_addr) /* gconf_type_ipv4 */, 0 /* FIXME: gconf_type_cidr */, sizeof (struct in_addr) /* gconf_type_host */, - sizeof (sockaddr_union_t) /* gconf_type_sockaddr */, + sizeof (struct gconf_sockaddr) /* gconf_type_sockaddr */, 0 /* gconf_type_section */ }; #define gconf_type_size_count \ diff --git a/gconf/gconf.h b/gconf/gconf.h index f88e87a..56792a0 100644 --- a/gconf/gconf.h +++ b/gconf/gconf.h @@ -97,6 +97,11 @@ struct gconf_keyword { struct gconf_keyword *kwd; }; +struct gconf_sockaddr { + int len; + struct sockaddr *sa; +}; + gconf_value_t *gconf_value_dup(gconf_value_t *input); extern void gconf_print_diag(gconf_locus_t *, int, int, const char*); diff --git a/src/Makefile.am b/src/Makefile.am index 7ba9832..903b754 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -25,8 +25,11 @@ wydawca_SOURCES=\ exec.c\ gpg.c\ interval.c\ + job.c\ meta.c\ method.c\ + net.c\ + pidfile.c\ process.c\ sql.c\ sql.h\ @@ -56,6 +59,7 @@ LDADD=../gconf/libgconf.a ../gnu/libgnu.a @SQLLIB@ @GPGMELIB@ @MAILUTILS_LIBS@ INCLUDES = -I$(top_srcdir)/gconf -I$(top_srcdir)/gnu -I../gnu @MAILUTILS_INCLUDES@ AM_CPPFLAGS= \ -DSYSCONFDIR=\"$(sysconfdir)\"\ + -DLOCALSTATEDIR=\"$(localstatedir)\"\ -DDEFAULT_VERSION_INCLUDE_DIR=\"$(incdir)\"\ -DDEFAULT_INCLUDE_DIR=\"$(pkgdatadir)/include\"\ -DDEFAULT_PREPROCESSOR="$(DEFAULT_PREPROCESSOR)" diff --git a/src/cmdline.opt b/src/cmdline.opt index 53bdd00..b61517b 100644 --- a/src/cmdline.opt +++ b/src/cmdline.opt @@ -18,6 +18,7 @@ static struct obstack pp_cmd_stack; static int pp_cmd_stack_init; static gl_list_t source_list; +static gl_list_t tag_list; static bool source_eq (const void *elt1, const void *elt2) @@ -28,9 +29,10 @@ source_eq (const void *elt1, const void *elt2) int enabled_spool_p (const struct spool *spool) { - if (!source_list) - return 1; - return !!gl_list_search (source_list, spool->source_dir); + if (source_list || tag_list) + return (source_list && gl_list_search (source_list, spool->source_dir)) + || (tag_list && gl_list_search (tag_list, spool->tag)); + return 1; } OPTIONS_BEGIN(gnu, "wydawca", @@ -61,12 +63,47 @@ BEGIN dry_run_mode = 1; END +OPTION(cron,,, + []) +BEGIN + cron_option = 1; + log_to_stderr = 0; +END + +OPTION(force,,, + []) +BEGIN + force_startup = 1; +END + +OPTION(foreground,,, + []) +BEGIN + foreground_option = 1; +END + +OPTION(single-process,,, + []) +BEGIN + single_process_option = 1; +END + OPTION(config-file,c,FILE, []) BEGIN conffile = optarg; END +OPTION(spool,S,TAG, + []) +BEGIN + if (!tag_list) + tag_list = gl_list_create_empty (&gl_linked_list_implementation, + source_eq, NULL, + NULL, false); + gl_list_add_last (tag_list, optarg); +END + OPTION(source,s,SOURCE-DIR, []) BEGIN @@ -79,9 +116,8 @@ END GROUP(Logging) -OPTION(cron,,, - []) -ALIAS(syslog) +OPTION(syslog,,, + []) BEGIN log_to_stderr = 0; END diff --git a/src/config.c b/src/config.c index dd444fe..94afb20 100644 --- a/src/config.c +++ b/src/config.c @@ -263,11 +263,6 @@ cb_mailer (enum gconf_callback_command cmd, if (assert_string_arg (locus, cmd, value)) return 1; - if (cmd != gconf_callback_set_value) - { - gconf_error (locus, 0, _("Unexpected block statement")); - return 1; - } rc = mu_mailer_create (&mailer, value->v.string); if (rc) gconf_error (locus, 0, _("cannot create mailer `%s': %s"), @@ -1085,22 +1080,17 @@ cb_access_method (enum gconf_callback_command cmd, } static int -cb_destination_url (enum gconf_callback_command cmd, - gconf_locus_t *locus, - void *varptr, - gconf_value_t *value, - void *cb_data) +cb_url (enum gconf_callback_command cmd, + gconf_locus_t *locus, + void *varptr, + gconf_value_t *value, + void *cb_data) { mu_url_t *purl = varptr, url; int rc; if (assert_string_arg (locus, cmd, value)) return 1; - if (cmd != gconf_callback_set_value) - { - gconf_error (locus, 0, _("Unexpected block statement")); - return 1; - } rc = mu_url_create (&url, value->v.string); if (rc) { @@ -1122,11 +1112,15 @@ cb_destination_url (enum gconf_callback_command cmd, static struct gconf_keyword spool_kw[] = { + { "url", N_("arg"), N_("URL corresponding to this spool"), + gconf_type_string, NULL, offsetof(struct spool, url) }, + { "alias", N_("arg"), N_("Aliases"), + gconf_type_string|GCONF_LIST, NULL, offsetof(struct spool, aliases) }, { "source", N_("dir"), N_("Source directory"), gconf_type_string, NULL, offsetof(struct spool, source_dir) }, { "destination", N_("dir"), N_("Destination directory"), gconf_type_string, NULL, offsetof(struct spool, dest_url), - cb_destination_url }, + cb_url }, { "file-sweep-time", N_("interval"), N_("Define file sweep time"), gconf_type_string, NULL, offsetof(struct spool, file_sweep_time), cb_interval }, @@ -1164,7 +1158,7 @@ cb_spool (enum gconf_callback_command cmd, return 1; } spool = xzalloc (sizeof (*spool)); - spool->url = xstrdup (value->v.string); + spool->tag = xstrdup (value->v.string); spool->file_sweep_time = file_sweep_time; for (i = 0; i < NITEMS (spool->access_method); i++) spool->access_method[i] = default_access_method[i]; @@ -1233,6 +1227,18 @@ cb_spool (enum gconf_callback_command cmd, static struct gconf_keyword wydawca_kw[] = { + { "daemon", NULL, N_("Enable daemon mode"), + gconf_type_bool, &daemon_mode }, + { "foreground", NULL, N_("Start in foreground even in daemon mode"), + gconf_type_bool, &foreground }, + { "single-process", NULL, N_("Do not spawn subprocesses"), + gconf_type_bool, &single_process }, + { "wakeup-interval", N_("time"), N_("Set wake-up interval"), + gconf_type_string, &wakeup_interval, 0, cb_interval }, + { "pidfile", N_("file"), N_("Set pid file name"), + gconf_type_string, &pidfile }, + { "listen", N_("socket"), N_("Listen on this address"), + gconf_type_sockaddr, &listen_sockaddr, }, { "mailer", N_("url"), N_("Set mailer URL"), gconf_type_string, &mailer, 0, cb_mailer }, { "admin-address", N_("email"), N_("Set admin email address"), diff --git a/src/directive.c b/src/directive.c index 46e3196..37ce241 100644 --- a/src/directive.c +++ b/src/directive.c @@ -302,7 +302,7 @@ verify_directive_format (struct file_triplet *trp) /* Process the directives from TRP, using given SPOOL */ int -process_directives (struct file_triplet *trp, struct spool *spool) +process_directives (struct file_triplet *trp, const struct spool *spool) { int rc, n; const char *key, *val; diff --git a/src/diskio.c b/src/diskio.c index 69a3cbe..ccff5c2 100644 --- a/src/diskio.c +++ b/src/diskio.c @@ -305,7 +305,7 @@ tar_append_file (const char *archive, const char *file) Do nothing if dry_run_mode is set. */ int backup_file (const char *dst_file, const char *dst_dir, const char *file, - struct archive_descr *archive, uid_t uid, gid_t gid, + const struct archive_descr *archive, uid_t uid, gid_t gid, const char *reldir) { int rc = 0; @@ -380,7 +380,7 @@ backup_file (const char *dst_file, const char *dst_dir, const char *file, for the argument description. */ int do_archive_file (const char *dst_file, const char *dst_dir, const char *file, - struct archive_descr *archive, uid_t uid, gid_t gid, + const struct archive_descr *archive, uid_t uid, gid_t gid, const char *reldir) { switch (archive->type) @@ -410,7 +410,7 @@ do_archive_file (const char *dst_file, const char *dst_dir, const char *file, Do nothing if dry_run_mode is set. */ int -dir_move_file (struct file_triplet *trp, struct spool *spool, +dir_move_file (struct file_triplet *trp, const struct spool *spool, enum file_type file_id, const char *reldir) { char *dst_file; @@ -447,7 +447,7 @@ dir_move_file (struct file_triplet *trp, struct spool *spool, Do nothing if dry_run_mode is set. */ int -archive_single_file (struct file_triplet *trp, struct spool *spool, +archive_single_file (struct file_triplet *trp, const struct spool *spool, const char *file_name, const char *reldir, int noentok) { @@ -517,7 +517,7 @@ make_signame (const char *file_name) Do nothing if dry_run_mode is set. */ int -dir_archive_file (struct file_triplet *trp, struct spool *spool, +dir_archive_file (struct file_triplet *trp, const struct spool *spool, const char *reldir, const char *file_name) { int rc; @@ -537,7 +537,7 @@ dir_archive_file (struct file_triplet *trp, struct spool *spool, Do nothing if dry_run_mode is set. */ int -dir_symlink_file (struct file_triplet *trp, struct spool *spool, +dir_symlink_file (struct file_triplet *trp, const struct spool *spool, const char *reldir, const char *wanted_src, const char *wanted_dst) { @@ -697,7 +697,7 @@ do_rmsymlink_file (const char *dst_file, int noentok) Do nothing if dry_run_mode is set. */ int -dir_rmsymlink_file (struct file_triplet *trp, struct spool *spool, +dir_rmsymlink_file (struct file_triplet *trp, const struct spool *spool, const char *reldir, const char *file_name) { char *dst_file; diff --git a/src/gpg.c b/src/gpg.c index d6e2301..6f7dfb6 100644 --- a/src/gpg.c +++ b/src/gpg.c @@ -203,7 +203,7 @@ gpg_sig_ok_p (gpgme_ctx_t ctx, gpgme_signature_t sig) /* FIXME: spool currently unused */ int verify_directive_signature (struct file_triplet *trp, - struct spool *spool, const char *pubkey) + const struct spool *spool, const char *pubkey) { gpgme_ctx_t ctx; gpgme_data_t key_data, directive_data, plain; @@ -261,7 +261,7 @@ verify_directive_signature (struct file_triplet *trp, a previous call to verify_directive_signature). */ int verify_detached_signature (struct file_triplet *trp, - struct spool *spool) + const struct spool *spool) { gpgme_engine_info_t info; const char *argv[5]; diff --git a/src/job.c b/src/job.c new file mode 100644 index 0000000..9678139 --- /dev/null +++ b/src/job.c @@ -0,0 +1,278 @@ +/* wydawca - automatic release submission daemon + Copyright (C) 2009 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 . */ + +#include "wydawca.h" + +#define STATE_FINISHED 0x01 +#define STATE_QUEUED 0x02 +#define STATE_ACTIVE 0x04 + +struct job +{ + struct job *next, *prev; + int state; + const struct spool *spool; + uid_t uid; + pid_t pid; + time_t timestamp; + int exit_status; +}; + +struct job *queue; +size_t jobmax; +size_t jobcnt; + +struct job * +job_locate (const struct spool *spool, uid_t uid) +{ + struct job *p; + for (p = queue; p; p = p->next) + if (p->spool == spool && p->uid == uid) + break; + return p; +} + +size_t +job_active_count () +{ + struct job *job; + size_t count = 0; + for (job = queue; job; job = job->next) + if (job->state & STATE_ACTIVE) + count++; + return count; +} + +void +wydawca_scanner (struct job *job) +{ + scan_spool (job->spool, 1, &job->uid); + mail_finish (); +} + +int +job_start (struct job *job) +{ + pid_t pid; + + if (jobmax && jobcnt == jobmax) + { + logmsg (LOG_NOTICE, "maximum number of processes active"); + return 1; + } + + if (debug_level) + logmsg (LOG_DEBUG, _("starting job: %s, %lu"), job->spool->tag, job->uid); + + if (single_process) + { + wydawca_scanner (job); + return 0; + } + + pid = fork (); + if (pid == 0) + { + wydawca_scanner (job); + exit (0); + } + else if (pid == -1) + { + logmsg (LOG_CRIT, "fork: %s", strerror (errno)); + return -1; + } + else + { + job->state = STATE_ACTIVE; + job->pid = pid; + jobcnt++; + } + return 0; +} + +void +job_remove (struct job *job) +{ + struct job *p; + + if (debug_level) + logmsg (LOG_DEBUG, _("removing job: %s, %lu"), job->spool->tag, job->uid); + p = job->prev; + if (p) + p->next = job->next; + else + queue = job->next; + + p = job->next; + if (p) + p->prev = job->prev; +} + +void +job_insert (struct job *job, struct job *elt) +{ + struct job *p; + + job->prev = elt; + if (!elt) + { + if (queue) + queue->prev = job; + job->next = queue; + queue = job; + return; + } + + p = elt->next; + elt->next = job; + + if (p) + p->prev = job; +} + +int +schedule_job (const struct spool *spool, uid_t uid) +{ + struct job *job; + + if (debug_level) + logmsg (LOG_DEBUG, _("scheduling job: %s, %lu"), spool->tag, uid); + + job = job_locate (spool, uid); + if (!job) + { + job = xzalloc (sizeof (*job)); + job->spool = spool; + job->uid = uid; + job->pid = -1; + time (&job->timestamp); + job_insert (job, NULL); + } + + job->state |= STATE_QUEUED; + job_start (job); +} + +static void +print_status (struct job *job, int expect_term) +{ + struct passwd *pw = getpwuid (job->uid); + int status = job->exit_status; + + if (WIFEXITED (status)) + { + if (WEXITSTATUS (status) == 0) + { + if (debug_level) + logmsg (LOG_DEBUG, + _("%lu (%s, %s) exited successfully"), + (unsigned long) job->pid, job->spool->tag, pw->pw_name); + } + else + logmsg (LOG_ERR, + _("%lu (%s, %s) failed with status %d"), + (unsigned long) job->pid, job->spool->tag, pw->pw_name, + WEXITSTATUS (status)); + } + else if (WIFSIGNALED (status)) + { + int prio; + if (expect_term && WTERMSIG (status) == SIGTERM) + { + if (!debug_level) + return; + prio = LOG_DEBUG; + } + else + prio = LOG_ERR; + + logmsg (prio, + _("%lu (%s, %s) terminated on signal %d"), + job->pid, job->spool->tag, pw->pw_name, WTERMSIG (status)); + } + else if (WIFSTOPPED (status)) + logmsg (LOG_NOTICE, + _("%lu (%s, %s) stopped on signal %d"), + job->pid, job->spool->tag, pw->pw_name, WSTOPSIG (status)); +#ifdef WCOREDUMP + else if (WCOREDUMP (status)) + logmsg (LOG_NOTICE, + _("%lu (%s, %s) dumped core"), + job->pid, job->spool->tag, pw->pw_name); +#endif + else + logmsg (LOG_ERR, + _("%lu (%s, %s) terminated with unrecognized status"), + job->pid, job->spool->tag, pw->pw_name); +} + +static int wakeup; + +RETSIGTYPE +queue_signal (int sig) +{ + wakeup = 1; + signal (sig, queue_signal); +} + +void +job_queue_runner () +{ + int status; + struct job *job; + + if (!wakeup) + return; + wakeup = 0; + + for (;;) + { + pid_t pid = waitpid ((pid_t)-1, &status, WNOHANG); + if (pid <= 0) + break; + for (job = queue; job; job = job->next) + { + if ((job->state & STATE_ACTIVE) && job->pid == pid) + { + job->state &= ~STATE_ACTIVE; + job->state |= STATE_FINISHED; + job->exit_status = status; + jobcnt--; + } + } + } + + for (job = queue; job;) + { + struct job *next = job->next; + if (job->state & STATE_FINISHED) + { + print_status (job, 0); + if ((job->state &= ~STATE_FINISHED) == 0) + job_remove (job); + } + if (job->state == STATE_QUEUED) + if (job_start (job)) + pause (); + job = next; + } +} + +void +job_init () +{ + signal (SIGCHLD, queue_signal); +} diff --git a/src/mail.c b/src/mail.c index 7987819..ea74b8c 100644 --- a/src/mail.c +++ b/src/mail.c @@ -104,7 +104,10 @@ void mail_finish () { if (mailer_opened) - mu_mailer_close (mailer); + { + mu_mailer_close (mailer); + mailer_opened = 0; + } } @@ -269,14 +272,14 @@ get_recipient (struct access_method *method, struct file_triplet *trp, if (method->type == method_none) { - *errp = "access method is not configured"; + *errp = N_("access method is not configured"); return NULL; } md = method_open (method); if (!md) { - *errp = "failed to open access method"; + *errp = N_("failed to open access method"); return NULL; } @@ -289,7 +292,7 @@ get_recipient (struct access_method *method, struct file_triplet *trp, free (text); if (rc) { - *errp = "cannot obtain recipient emails"; + *errp = N_("cannot obtain recipient emails"); method_close (method, md); return NULL; } @@ -299,7 +302,7 @@ get_recipient (struct access_method *method, struct file_triplet *trp, if (nrows == 0) { - *errp = "cannot obtain recipient emails"; + *errp = N_("cannot obtain recipient emails"); return NULL; } @@ -350,7 +353,7 @@ do_notify (struct file_triplet *trp, enum notification_event ev, logmsg (LOG_ERR, _("not notifying %s (project %s) about %s: %s"), notification_target_str (ntf->tgt), trp->project, - notification_event_str (ev), errp); + notification_event_str (ev), gettext (errp)); return; } diff --git a/src/net.c b/src/net.c new file mode 100644 index 0000000..efb6225 --- /dev/null +++ b/src/net.c @@ -0,0 +1,227 @@ +/* wydawca - automatic release submission daemon + Copyright (C) 2007, 2009 Sergey Poznyakoff + + Wydawca 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. + + Wydawca 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 wydawca. If not, see . */ + +#include "wydawca.h" + +static int +open_listener () +{ + int fd; + + if (listen_sockaddr.sa == NULL) + { + logmsg (LOG_CRIT, _("listener address is not configured")); + exit (1); + } + + fd = socket (listen_sockaddr.sa->sa_family, SOCK_STREAM, 0); + if (fd == -1) + { + logmsg (LOG_CRIT, _("cannot create socket: %s"), + strerror(errno)); + exit (1); + } + if (listen_sockaddr.sa->sa_family == AF_UNIX) + { + struct stat st; + struct sockaddr_un *s_un = (struct sockaddr_un *) listen_sockaddr.sa; + if (stat (s_un->sun_path, &st)) + { + if (errno != ENOENT) + { + logmsg (LOG_CRIT, _("%s: cannot stat socket: %s"), + s_un->sun_path, strerror (errno)); + exit (1); + } + } + else + { + /* FIXME: Check permissions? */ + if (!S_ISSOCK (st.st_mode)) + { + logmsg (LOG_CRIT, _("%s: not a socket"), + s_un->sun_path, strerror (errno)); + exit (1); + } + unlink (s_un->sun_path); + } + /* FIXME: Setup umask */ + } + else + { + int yes = 1; + setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (void *) &yes, sizeof(yes)); + } + + if (bind (fd, listen_sockaddr.sa, listen_sockaddr.len) < 0) + { + logmsg (LOG_CRIT, _("cannot bind to local address: %s"), + strerror (errno)); + close (fd); + exit (1); + } + if (listen (fd, 8) == -1) + { + logmsg (LOG_CRIT, "listen: %s", strerror (errno)); + close (fd); + exit (1); + } + + return fd; +} + +static void +trim_crlf (char *s) +{ + size_t len = strlen (s); + if (len > 0 && s[len-1] == '\n') + { + s[--len] = 0; + if (len > 0 && s[len-1] == '\r') + s[--len] = 0; + } +} + +void +handle_connection (FILE *fp) +{ + char *buf = NULL; + size_t buflen = 0; + const struct spool *spool; + char *p; + struct passwd *pw; + + if (getline (&buf, &buflen, fp) <= 0) + return; + trim_crlf (buf); + if (debug_level) + logmsg (LOG_DEBUG, "recv: %s", buf); + spool = wydawca_find_spool (buf); + if (!spool) + { + fprintf (fp, "- Unknown service name\r\n"); + free (buf); + return; + } + else if (spool->url) + fprintf (fp, "+ OK, URL %s\r\n", spool->url); + else + fprintf (fp, "+ OK, spool %s\r\n", spool->tag); + + if (getline (&buf, &buflen, fp) <= 0) + { + logmsg (LOG_ERR, "protocol error"); + free (buf); + return; + } + + if (debug_level) + logmsg (LOG_DEBUG, "recv: %s", buf); + + p = strchr (buf, ' '); + if (p) + { + *p++ = 0; + while (*p && (*p == ' ' || *p == '\t')) + p++; + } + else + p = ""; + + pw = getpwnam (buf); + if (pw) + schedule_job (spool, pw->pw_uid); + else + logmsg (LOG_ERR, "no such user: %s", buf); + free (buf); +} + +static int reconfigure; +static int terminate; + +RETSIGTYPE +sig_hup (int sig) +{ + reconfigure = 1; + terminate = 1; +} + +RETSIGTYPE +sig_term (int sig) +{ + terminate = 1; +} + +void +wydawca_listener () +{ + int ctlfd = open_listener (); + + job_init (); + signal (SIGHUP, sig_hup); + signal (SIGTERM, sig_term); + signal (SIGQUIT, sig_term); + signal (SIGINT, sig_term); + while (!terminate) + { + int fd; + FILE *fp; + int rc; + fd_set rset; + struct timeval to, *pto; + union { + struct sockaddr sa; + struct sockaddr_in s_in; + struct sockaddr_un s_un; + } addr; + socklen_t len; + + job_queue_runner (); + FD_ZERO (&rset); + FD_SET (ctlfd, &rset); + + if (wakeup_interval) + { + to.tv_sec = wakeup_interval; + to.tv_usec = 0; + *pto = to; + } + else + pto = NULL; + + rc = select (ctlfd + 1, &rset, NULL, NULL, pto); + if (rc == 0) + continue; + else if (rc < 0) + { + if (errno == EINTR) + continue; + logmsg (LOG_ERR, "select: %s", strerror (errno)); + break; + } + + len = sizeof (addr); + fd = accept (ctlfd, (struct sockaddr*) &addr, &len); + if (fd == -1) + continue; + /* FIXME: Check if the connection is allowed */ + fp = fdopen (fd, "r+"); + handle_connection (fp); + fclose (fp); + } +} + + diff --git a/src/null.c b/src/null.c index 7ead150..6a1b0a7 100644 --- a/src/null.c +++ b/src/null.c @@ -17,13 +17,13 @@ #include "wydawca.h" int -null_move_file (struct file_triplet *trp, struct spool *spool, +null_move_file (struct file_triplet *trp, const struct spool *spool, enum file_type file_id, const char *reldir) { const char *file_name = trp->file[file_id].name; if (debug_level) - logmsg (LOG_DEBUG, _("%s: installing file `%s/%s'"), - spool->url, reldir, file_name); + logmsg (LOG_DEBUG, _("spool %s: installing file `%s/%s'"), + spool->tag, reldir, file_name); UPDATE_STATS (STAT_UPLOADS); if (unlink (file_name)) { @@ -35,34 +35,34 @@ null_move_file (struct file_triplet *trp, struct spool *spool, } int -null_archive_file (struct file_triplet *trp, struct spool *spool, +null_archive_file (struct file_triplet *trp, const struct spool *spool, const char *file_name, const char *reldir) { if (debug_level) - logmsg (LOG_DEBUG, _("%s: archiving `%s'"), spool->url, file_name); + logmsg (LOG_DEBUG, _("spool %s: archiving `%s'"), spool->tag, file_name); UPDATE_STATS (STAT_ARCHIVES); return 0; } int -null_symlink_file (struct file_triplet *trp, struct spool *spool, +null_symlink_file (struct file_triplet *trp, const struct spool *spool, const char *reldir, const char *wanted_src, const char *wanted_dst) { if (debug_level) - logmsg (LOG_DEBUG, _("%s: symlinking `%s' to `%s'"), - spool->url, wanted_src, wanted_dst); + logmsg (LOG_DEBUG, _("spool %s: symlinking `%s' to `%s'"), + spool->tag, wanted_src, wanted_dst); UPDATE_STATS (STAT_SYMLINKS); return 0; } int -null_rmsymlink_file (struct file_triplet *trp, struct spool *spool, +null_rmsymlink_file (struct file_triplet *trp, const struct spool *spool, const char *reldir, const char *file_name) { if (debug_level) - logmsg (LOG_DEBUG, _("%s: removing symlink `%s/%s'"), - spool->url, reldir, file_name); + logmsg (LOG_DEBUG, _("spool %s: removing symlink `%s/%s'"), + spool->tag, reldir, file_name); UPDATE_STATS (STAT_RMSYMLINKS); return 0; } diff --git a/src/pidfile.c b/src/pidfile.c new file mode 100644 index 0000000..484cabd --- /dev/null +++ b/src/pidfile.c @@ -0,0 +1,90 @@ +/* wydawca - automatic release submission daemon + Copyright (C) 2007, 2009 Sergey Poznyakoff + + Wydawca 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. + + Wydawca 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 wydawca. If not, see . */ + +#include "wydawca.h" + +char *pidfile = LOCALSTATEDIR "/run/wydawca.pid"; +int force_startup; + + +void +remove_pidfile (void) +{ + unlink (pidfile); +} + +void +check_pidfile () +{ + FILE *fp = fopen (pidfile, "r+"); + + if (fp) + { + unsigned long pid; + if (fscanf (fp, "%ul\n", &pid) != 1) + { + logmsg (LOG_ERR, _("malformed pidfile %s"), pidfile); + if (!force_startup) + exit (1); + } + else + { + if (kill (pid, 0)) + { + if (errno != ESRCH) + { + logmsg (LOG_ERR, + _("cannot verify if PID %lu is running: %s"), + pid, strerror (errno)); + if (!force_startup) + exit (1); + } + } + else if (!force_startup) + { + logmsg (LOG_ERR, + _("another wydawca instance may be running (PID %lu)"), + pid); + exit (1); + } + } + logmsg (LOG_NOTICE, _("replacing pidfile %s (PID %lu)"), + pidfile, pid); + fseek (fp, 0, SEEK_SET); + } + else if (errno != ENOENT) + { + logmsg (LOG_ERR, _("cannot open pidfile %s: %s"), pidfile, + strerror (errno)); + exit (1); + } + else + { + fp = fopen (pidfile, "w"); + if (!fp) + { + logmsg (LOG_ERR, + _("cannot open pidfile %s for writing: %s"), + pidfile, strerror (errno)); + exit (1); + } + } + fprintf (fp, "%lu\n", getpid ()); + fclose (fp); + atexit (remove_pidfile); +} + + diff --git a/src/process.c b/src/process.c index 0d2bf5e..20bfd38 100644 --- a/src/process.c +++ b/src/process.c @@ -33,6 +33,41 @@ register_spool (struct spool *spool) spool_list = sp; } +static int +spool_check_alias (struct spool *spool, const char *name) +{ + int rc = 0; + + if (spool->aliases) + { + gl_list_iterator_t itr = gl_list_iterator (spool->aliases); + const void *p; + + while (gl_list_iterator_next (&itr, &p, NULL)) + if (strcmp (name, p) == 0) + { + rc = 1; + break; + } + gl_list_iterator_free (&itr); + } + return rc; +} + +struct spool * +wydawca_find_spool (const char *name) +{ + struct spool_list *sp; + + for (sp = spool_list; sp; sp = sp->next) + { + if (strcmp (sp->spool.tag, name) == 0 + || spool_check_alias (&sp->spool, name)) + return &sp->spool; + } + return NULL; +} + /* Return true if NAME is a directory. If stat fails, return the error code in EC */ int @@ -100,10 +135,22 @@ parse_file_name (const char *name, struct file_info *finfo) abort (); /* should not happen */ } +int +match_uid_p (uid_t uid, int uc, uid_t *uv) +{ + int i; + if (!uv) + return 1; + for (i = 0; i < uc; i++) + if (uv[i] == uid) + return 1; + return 0; +} + /* Scan upload directory from the DPAIR and register all files found there, forming triplets when possible */ void -scan_spool (struct spool *spool) +scan_spool (const struct spool *spool, int uc, uid_t *uv) { DIR *dir; struct dirent *ent; @@ -127,8 +174,9 @@ scan_spool (struct spool *spool) return; } - timer_start ("directory"); - timer_start (spool->url); + timer_start ("spool"); + /* FIXME: prefix spool tag with something */ + timer_start (spool->tag); while ((ent = readdir (dir))) { struct stat st; @@ -152,7 +200,7 @@ scan_spool (struct spool *spool) continue; } - if (!match_uid_p (st.st_uid)) + if (!match_uid_p (st.st_uid, uc, uv)) { if (debug_level) logmsg (LOG_DEBUG, _("ignoring file: %s/%s"), @@ -164,7 +212,7 @@ scan_spool (struct spool *spool) parse_file_name (ent->d_name, &finfo); if (debug_level) - logmsg (LOG_DEBUG, _("file %s: %s, root %.*s"), ent->d_name, + logmsg (LOG_DEBUG, _("found file %s: %s, stem: %.*s"), ent->d_name, file_type_str (finfo.type), finfo.root_len, finfo.name); register_file (&finfo); @@ -186,8 +234,8 @@ scan_spool (struct spool *spool) } enumerate_triplets (spool); } - timer_stop (spool->url); - timer_stop ("directory"); + timer_stop (spool->tag); + timer_stop ("spool"); } static void @@ -200,7 +248,7 @@ close_methods (struct spool *spool) /* Scan all configured update directories */ void -scan_directories () +scan_directories (int uidc, uid_t *uidv) { struct spool_list *sp; @@ -208,7 +256,7 @@ scan_directories () for (sp = spool_list; sp; sp = sp->next) if (enabled_spool_p (&sp->spool)) - scan_spool (&sp->spool); + scan_spool (&sp->spool, uidc, uidv); for (sp = spool_list; sp; sp = sp->next) close_methods (&sp->spool); diff --git a/src/triplet.c b/src/triplet.c index 6641211..717fd2a 100644 --- a/src/triplet.c +++ b/src/triplet.c @@ -182,7 +182,7 @@ static bool triplet_processor (void *data, void *proc_data) { struct file_triplet *trp = data; - struct spool *spool = proc_data; + const struct spool *spool = proc_data; trp->spool = spool; @@ -230,14 +230,14 @@ triplet_processor (void *data, void *proc_data) /* Process all triplets from the table according to the SPOOL */ void -enumerate_triplets (struct spool *spool) +enumerate_triplets (const struct spool *spool) { if (debug_level) - logmsg (LOG_DEBUG, _("processing files for %s (%s)"), - spool->url, mu_url_to_string (spool->dest_url)); + logmsg (LOG_DEBUG, _("processing spool %s (%s)"), + spool->tag, mu_url_to_string (spool->dest_url)); if (triplet_table) { - hash_do_for_each (triplet_table, triplet_processor, spool); + hash_do_for_each (triplet_table, triplet_processor, (void*) spool); hash_clear (triplet_table); } } @@ -256,6 +256,13 @@ expand_project_base (struct metadef *def, void *data) return trp->project; } +static const char * +expand_tag (struct metadef *def, void *data) +{ + struct file_triplet *trp = data; + return trp->spool->tag; +} + static const char * expand_url (struct metadef *def, void *data) { @@ -576,6 +583,7 @@ DECL_EXPAND_TIMER(system) struct metadef triplet_meta[] = { { "project", NULL, expand_project_base, NULL }, { "url", NULL, expand_url, NULL }, + { "spool", NULL, expand_tag, NULL }, { "dir", NULL, expand_relative_dir, NULL }, { "dest-dir", NULL, expand_dest_dir, NULL }, { "source-dir", NULL, expand_source_dir, NULL }, diff --git a/src/verify.c b/src/verify.c index 14651d2..522b865 100644 --- a/src/verify.c +++ b/src/verify.c @@ -92,7 +92,7 @@ make_default_meta (struct metadef def[5], const char *user, /* Verify if USER has upload rights on the directory (project) requested by TRP */ int -check_access_rights (struct file_triplet *trp, struct spool *spool, +check_access_rights (struct file_triplet *trp, const struct spool *spool, const char *user) { struct access_method *method = spool->access_method[verify_method]; @@ -143,7 +143,7 @@ check_access_rights (struct file_triplet *trp, struct spool *spool, } int -verify_directive_file (struct file_triplet *trp, struct spool *spool) +verify_directive_file (struct file_triplet *trp, const struct spool *spool) { struct passwd *pw; char *command; diff --git a/src/vtab.c b/src/vtab.c index c34896c..36d8af8 100644 --- a/src/vtab.c +++ b/src/vtab.c @@ -51,7 +51,7 @@ url_to_vtab (mu_url_t url, struct virt_tab *vtab) int -move_file (struct file_triplet *trp, struct spool *spool, +move_file (struct file_triplet *trp, const const struct spool *spool, enum file_type file_id, const char *reldir) { int rc = spool->vtab.move_file (trp, spool, file_id, reldir); @@ -61,7 +61,7 @@ move_file (struct file_triplet *trp, struct spool *spool, } int -archive_file (struct file_triplet *trp, struct spool *spool, +archive_file (struct file_triplet *trp, const struct spool *spool, const char *reldir, const char *file_name) { int rc = spool->vtab.archive_file (trp, spool, reldir, file_name); @@ -71,7 +71,7 @@ archive_file (struct file_triplet *trp, struct spool *spool, } int -symlink_file (struct file_triplet *trp, struct spool *spool, +symlink_file (struct file_triplet *trp, const struct spool *spool, const char *reldir, const char *wanted_src, const char *wanted_dst) { @@ -84,7 +84,7 @@ symlink_file (struct file_triplet *trp, struct spool *spool, } int -rmsymlink_file (struct file_triplet *trp, struct spool *spool, +rmsymlink_file (struct file_triplet *trp, const struct spool *spool, const char *reldir, const char *file_name) { int rc = spool->vtab.rmsymlink_file (trp, spool, reldir, file_name); diff --git a/src/wydawca.c b/src/wydawca.c index ce78fc1..cc6c8f0 100644 --- a/src/wydawca.c +++ b/src/wydawca.c @@ -32,6 +32,16 @@ char *tar_command_name = "tar"; int archive_signatures = 1; /* Archive sig files by default */ int lint_mode = 0; int preprocess_only = 0; +int cron_option = 0; +int foreground_option = -1; +int single_process_option = -1; + +int daemon_mode = 0; +int foreground; +int single_process; +time_t wakeup_interval; + +struct gconf_sockaddr listen_sockaddr; unsigned wydawca_stat[MAX_STAT]; @@ -106,46 +116,20 @@ logmsg (int prio, char *fmt, ...) } - -enum { - SYSLOG_OPTION = 256, - CONFIG_HELP_OPTION, - DUMP_GRAMMAR_TRACE_OPTION, - DUMP_LEX_TRACE_OPTION -}; - -struct option options[] = { - { "config-file", required_argument, NULL, 'c' }, - { "config-help", no_argument, NULL, CONFIG_HELP_OPTION }, - { "dump-grammar-trace", no_argument, NULL, DUMP_GRAMMAR_TRACE_OPTION }, - { "dump-lex-trace", no_argument, NULL, DUMP_LEX_TRACE_OPTION }, - { "debug", no_argument, NULL, 'd' }, - { "stderr", no_argument, NULL, 'e' }, - { "syslog", no_argument, NULL, SYSLOG_OPTION }, - { "cron", no_argument, NULL, SYSLOG_OPTION }, - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, 'v' }, - { "dry-run", no_argument, NULL, 'n' }, - { "lint", no_argument, NULL, 't' }, - { "include-directory", optional_argument, NULL, 'I' }, - { NULL } -}; - - static char *stat_name[MAX_STAT] = { - "errors", - "warnings", - "bad signatures", - "access violation attempts", - "complete triplets", - "incomplete triplets", - "bad triplets", - "expired triplets", - "triplet successes", - "files uploaded", - "files archived", - "symlinks created", - "symlinks removed", + N_("errors"), + N_("warnings"), + N_("bad signatures"), + N_("access violation attempts"), + N_("complete triplets"), + N_("incomplete triplets"), + N_("bad triplets"), + N_("expired triplets"), + N_("triplet successes"), + N_("files uploaded"), + N_("files archived"), + N_("symlinks created"), + N_("symlinks removed"), }; static char *stat_kwname[MAX_STAT] = { @@ -212,7 +196,7 @@ 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]); + logmsg (LOG_INFO, "%s: %u", gettext (stat_name[i]), wydawca_stat[i]); } mail_stats (); @@ -244,7 +228,7 @@ gconf_print_diag (gconf_locus_t *locus, int err, int errcode, const char *msg) static int uidc; -static char *uidv; +static uid_t *uidv; static int collect_uids (int argc, char **argv) @@ -272,18 +256,6 @@ collect_uids (int argc, char **argv) } } -int -match_uid_p (uid_t uid) -{ - int i; - if (!uidv) - return 1; - for (i = 0; i < uidc; i++) - if (uidv[i] == uid) - return 1; - return 0; -} - int wydawca_uid (uid_t uid) @@ -308,6 +280,21 @@ wydawca_uid (uid_t uid) } +void +wydawca_daemon () +{ + check_pidfile (); + + if (!foreground && daemon (0, 0)) + { + logmsg (LOG_ERR, "%s", strerror (errno)); + exit (1); + } + + wydawca_listener (); +} + + #include "cmdline.h" int @@ -333,8 +320,15 @@ main (int argc, char **argv) if (lint_mode) exit (0); + if (cron_option) + daemon_mode = 0; + if (foreground_option >= 0) + foreground = foreground_option; + if (single_process_option >= 0) + single_process = single_process_option; + if (log_to_stderr == -1) - log_to_stderr = isatty (0); + log_to_stderr = (!daemon_mode || foreground) && isatty (0); gconf_log_to_stderr = log_to_stderr; if (!log_to_stderr) @@ -346,10 +340,16 @@ main (int argc, char **argv) mail_init (); logmsg (LOG_NOTICE, _("wydawca (%s) started"), PACKAGE_STRING); - scan_directories (); + if (!daemon_mode) + { + scan_directories (uidc, uidv); + logstats (); + } + else + wydawca_daemon (); + logmsg (LOG_NOTICE, _("wydawca (%s) finished"), PACKAGE_STRING); - logstats (); mail_finish (); diff --git a/src/wydawca.h b/src/wydawca.h index 3f28919..8a716e4 100644 --- a/src/wydawca.h +++ b/src/wydawca.h @@ -32,7 +32,14 @@ #include #include #include +#include +#include +#include +#include +#include +#include #include +#include #include #include @@ -47,6 +54,7 @@ #include "backupfile.h" #include "inttostr.h" #include "gconf.h" +#include "gl_list.h" #include "argcv.h" #define gettext(s) s @@ -156,7 +164,7 @@ struct file_triplet char *name; /* Triplet base name */ gid_t gid; /* Owner GID */ struct file_info file[FILE_TYPE_COUNT]; /* Components */ - struct spool *spool; /* Owning spool */ + const struct spool *spool; /* Owning spool */ char **directive; /* Decoded directive pairs (key: value\0) */ char *blurb; /* Block of directives: directive[i] points here */ char *tmp; /* Temporary storage */ @@ -179,20 +187,20 @@ struct virt_tab { int (*test_url) (mu_url_t url, gconf_locus_t *loc); int (*move_file) (struct file_triplet *trp, - struct spool *spool, + const struct spool *spool, enum file_type file_id, const char *reldir); int (*archive_file) (struct file_triplet *trp, - struct spool *spool, + const struct spool *spool, const char *reldir, const char *file_name); int (*symlink_file) (struct file_triplet *trp, - struct spool *spool, + const struct spool *spool, const char *reldir, const char *wanted_src, const char *wanted_dst); int (*rmsymlink_file)(struct file_triplet *trp, - struct spool *spool, + const struct spool *spool, const char *reldir, const char *file_name); }; @@ -201,6 +209,8 @@ struct virt_tab files from source to destination */ struct spool { + char *tag; + gl_list_t aliases; char *url; /* Download URL */ char *source_dir; /* Source directory */ mu_url_t dest_url; /* Destination URL */ @@ -306,6 +316,15 @@ extern int archive_signatures; extern char *admin_stat_message; +extern char *pidfile; +extern int force_startup; + +extern int daemon_mode; +extern time_t wakeup_interval; +extern int foreground; +extern int single_process; +extern struct gconf_sockaddr listen_sockaddr; + #define UPDATE_STATS(what) \ do \ { \ @@ -341,10 +360,13 @@ enum exec_result wydawca_exec (int argc, const char **argv, int *retcode); /* Directory scanning and registering */ -void scan_directories (void); +void scan_spool (const struct spool *spool, int uc, uid_t *uv); +void scan_directories (int, uid_t *); + void register_spool (struct spool *spool); +struct spool *wydawca_find_spool (const char *name); void register_file (struct file_info *finfo); -void enumerate_triplets (struct spool *); +void enumerate_triplets (const struct spool *); size_t count_collected_triplets (void); char *triplet_expand_param (const char *tmpl, struct file_triplet *trp); @@ -369,12 +391,12 @@ unsigned method_num_cols (struct access_method *method); /* Verification functions */ int verify_directive_file (struct file_triplet *trp, - struct spool *spool); + const struct spool *spool); int verify_directive_signature (struct file_triplet *trp, - struct spool *spool, + const struct spool *spool, const char *pubkey); int verify_detached_signature (struct file_triplet *trp, - struct spool *spool); + const struct spool *spool); int fill_project_name (struct file_triplet *trp); /* Directive file support */ @@ -390,9 +412,8 @@ int directive_first (struct file_triplet *trp, int directive_next (struct file_triplet *trp, int n, const char **pkey, const char **pval); int process_directives (struct file_triplet *trp, - struct spool *spool); + const struct spool *spool); -int match_uid_p (uid_t uid); int enabled_spool_p (const struct spool *spool); int wydawca_uid (uid_t uid); @@ -410,42 +431,42 @@ void config_help (void); int url_to_vtab (mu_url_t url, struct virt_tab *vtab); int -move_file (struct file_triplet *trp, struct spool *spool, +move_file (struct file_triplet *trp, const struct spool *spool, enum file_type file_id, const char *reldir); int -archive_file (struct file_triplet *trp, struct spool *spool, +archive_file (struct file_triplet *trp, const struct spool *spool, const char *reldir, const char *file_name); int -symlink_file (struct file_triplet *trp, struct spool *spool, +symlink_file (struct file_triplet *trp, const struct spool *spool, const char *reldir, const char *wanted_src, const char *wanted_dst); int -rmsymlink_file (struct file_triplet *trp, struct spool *spool, +rmsymlink_file (struct file_triplet *trp, const struct spool *spool, const char *reldir, const char *file_name); /* diskio.c */ int dir_test_url (mu_url_t url, gconf_locus_t *locus); -int dir_move_file (struct file_triplet *trp, struct spool *spool, +int dir_move_file (struct file_triplet *trp, const struct spool *spool, enum file_type file_id, const char *reldir); -int dir_archive_file (struct file_triplet *trp, struct spool *spool, +int dir_archive_file (struct file_triplet *trp, const struct spool *spool, const char *file_name, const char *reldir); -int dir_symlink_file (struct file_triplet *trp, struct spool *spool, +int dir_symlink_file (struct file_triplet *trp, const struct spool *spool, const char *reldir, const char *wanted_src, const char *wanted_dst); -int dir_rmsymlink_file (struct file_triplet *trp, struct spool *spool, +int dir_rmsymlink_file (struct file_triplet *trp, const struct spool *spool, const char *reldir, const char *file_name); /* null.c */ -int null_move_file (struct file_triplet *trp, struct spool *spool, +int null_move_file (struct file_triplet *trp, const struct spool *spool, enum file_type file_id, const char *reldir); -int null_archive_file (struct file_triplet *trp, struct spool *spool, +int null_archive_file (struct file_triplet *trp, const struct spool *spool, const char *file_name, const char *reldir); -int null_symlink_file (struct file_triplet *trp, struct spool *spool, +int null_symlink_file (struct file_triplet *trp, const struct spool *spool, const char *reldir, const char *wanted_src, const char *wanted_dst); -int null_rmsymlink_file (struct file_triplet *trp, struct spool *spool, +int null_rmsymlink_file (struct file_triplet *trp, const struct spool *spool, const char *reldir, const char *file_name); @@ -469,3 +490,17 @@ void report_init (void); void report_add (const char *fmt, ...); void report_finish (void); extern char *report_string; + + +/* job.c */ +int schedule_job (const struct spool *spool, uid_t uid); +void job_init (void); +void job_queue_runner (void); + + +/* profile.c */ +void check_pidfile (void); + + +/* net.c */ +void wydawca_listener (void); diff --git a/tests/etc/wydawca.rcin b/tests/etc/wydawca.rcin index f897cf9..36ef7a2 100644 --- a/tests/etc/wydawca.rcin +++ b/tests/etc/wydawca.rcin @@ -76,7 +76,8 @@ access-method gpg-key { "-----END PGP PUBLIC KEY BLOCK-----\n"); } -spool ftp://wydawca.test { +spool test { + url ftp://wydawca.test; source "@WD_SRC@"; destination "@WD_DST@"; archive none; diff --git a/tests/mailstats.at b/tests/mailstats.at index b26c832..ff16f2a 100644 --- a/tests/mailstats.at +++ b/tests/mailstats.at @@ -19,7 +19,6 @@ AT_SETUP([Simple upload statistics]) AT_DATA([errtmpl], [wydawca: [[NOTICE]] AT_PACKAGE_TARNAME (AT_PACKAGE_NAME AT_PACKAGE_VERSION) started wydawca: [[NOTICE]] file.directive.asc: COMMENT: Gnupload for Wydawca testsuite -wydawca: [[NOTICE]] AT_PACKAGE_TARNAME (AT_PACKAGE_NAME AT_PACKAGE_VERSION) finished wydawca: [[INFO]] errors: 0 wydawca: [[INFO]] warnings: 0 wydawca: [[INFO]] bad signatures: 0 @@ -33,6 +32,7 @@ wydawca: [[INFO]] files uploaded: 2 wydawca: [[INFO]] files archived: 0 wydawca: [[INFO]] symlinks created: 0 wydawca: [[INFO]] symlinks removed: 0 +wydawca: [[NOTICE]] AT_PACKAGE_TARNAME (AT_PACKAGE_NAME AT_PACKAGE_VERSION) finished ]) AT_DATA([expout], diff --git a/tests/notify-upl.at b/tests/notify-upl.at index ca57846..9efe1d9 100644 --- a/tests/notify-upl.at +++ b/tests/notify-upl.at @@ -19,7 +19,6 @@ AT_SETUP([Simple upload and notification]) AT_DATA([errtmpl], [wydawca: [[NOTICE]] AT_PACKAGE_TARNAME (AT_PACKAGE_NAME AT_PACKAGE_VERSION) started wydawca: [[NOTICE]] file.directive.asc: COMMENT: Gnupload for Wydawca testsuite -wydawca: [[NOTICE]] AT_PACKAGE_TARNAME (AT_PACKAGE_NAME AT_PACKAGE_VERSION) finished wydawca: [[INFO]] errors: 0 wydawca: [[INFO]] warnings: 0 wydawca: [[INFO]] bad signatures: 0 @@ -33,6 +32,7 @@ wydawca: [[INFO]] files uploaded: 2 wydawca: [[INFO]] files archived: 0 wydawca: [[INFO]] symlinks created: 0 wydawca: [[INFO]] symlinks removed: 0 +wydawca: [[NOTICE]] AT_PACKAGE_TARNAME (AT_PACKAGE_NAME AT_PACKAGE_VERSION) finished ]) AT_DATA([outtmpl], diff --git a/tests/upload-dry.at b/tests/upload-dry.at index 306f6f3..6ea1f2d 100644 --- a/tests/upload-dry.at +++ b/tests/upload-dry.at @@ -19,10 +19,10 @@ AT_SETUP([Dry-run upload]) AT_DATA([template], [wydawca: [[NOTICE]] AT_PACKAGE_TARNAME (AT_PACKAGE_NAME AT_PACKAGE_VERSION) started wydawca: [[DEBUG]] @WD_SRC@ -> @WD_DST@ -wydawca: [[DEBUG]] file file is a distributive, root file -wydawca: [[DEBUG]] file file.directive.asc is a signed upload directive, root file -wydawca: [[DEBUG]] file file.sig is a detached signature, root file -wydawca: [[DEBUG]] processing files for ftp://wydawca.test (@WD_DST@) +wydawca: [[DEBUG]] found file file: distributive, stem: file +wydawca: [[DEBUG]] found file file.directive.asc: signed upload directive, stem: file +wydawca: [[DEBUG]] found file file.sig: detached signature, stem: file +wydawca: [[DEBUG]] processing spool test (@WD_DST@) wydawca: [[DEBUG]] FILE file, DIST=file, SIG=file.sig, DIRECTIVE=file.directive.asc wydawca: [[NOTICE]] Good signature from Wydawca (Testsuite) wydawca: [[DEBUG]] file: directive file signature OK @@ -32,7 +32,6 @@ wydawca: [[NOTICE]] file.directive.asc: COMMENT: Gnupload for Wydawca testsuite wydawca: [[DEBUG]] good detached signature for file wydawca: [[DEBUG]] installing file to @WD_DST@/proj wydawca: [[DEBUG]] installing file.sig to @WD_DST@/proj -wydawca: [[NOTICE]] AT_PACKAGE_TARNAME (AT_PACKAGE_NAME AT_PACKAGE_VERSION) finished wydawca: [[INFO]] errors: 0 wydawca: [[INFO]] warnings: 0 wydawca: [[INFO]] bad signatures: 0 @@ -46,6 +45,7 @@ wydawca: [[INFO]] files uploaded: 2 wydawca: [[INFO]] files archived: 0 wydawca: [[INFO]] symlinks created: 0 wydawca: [[INFO]] symlinks removed: 0 +wydawca: [[NOTICE]] AT_PACKAGE_TARNAME (AT_PACKAGE_NAME AT_PACKAGE_VERSION) finished ]) AT_CHECK([ diff --git a/tests/upload.at b/tests/upload.at index 1f3696c..1968658 100644 --- a/tests/upload.at +++ b/tests/upload.at @@ -19,7 +19,6 @@ AT_SETUP([Simple upload]) AT_DATA([template], [wydawca: [[NOTICE]] AT_PACKAGE_TARNAME (AT_PACKAGE_NAME AT_PACKAGE_VERSION) started wydawca: [[NOTICE]] file.directive.asc: COMMENT: Gnupload for Wydawca testsuite -wydawca: [[NOTICE]] AT_PACKAGE_TARNAME (AT_PACKAGE_NAME AT_PACKAGE_VERSION) finished wydawca: [[INFO]] errors: 0 wydawca: [[INFO]] warnings: 0 wydawca: [[INFO]] bad signatures: 0 @@ -33,6 +32,7 @@ wydawca: [[INFO]] files uploaded: 2 wydawca: [[INFO]] files archived: 0 wydawca: [[INFO]] symlinks created: 0 wydawca: [[INFO]] symlinks removed: 0 +wydawca: [[NOTICE]] AT_PACKAGE_TARNAME (AT_PACKAGE_NAME AT_PACKAGE_VERSION) finished ]) AT_CHECK([ -- cgit v1.2.1