aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/wydawca.texi177
-rw-r--r--src/Makefile.am2
-rw-r--r--src/builtin.c46
-rw-r--r--src/builtin.h12
-rw-r--r--src/config.c104
-rw-r--r--src/dictionary.c228
-rw-r--r--src/mail.c28
-rw-r--r--src/meta.c10
-rw-r--r--src/method.c226
-rw-r--r--src/process.c14
-rw-r--r--src/sql.c44
-rw-r--r--src/sql.h20
-rw-r--r--src/triplet.c8
-rw-r--r--src/verify.c32
-rw-r--r--src/wydawca.h60
-rw-r--r--tests/etc/wydawca.rcin4
16 files changed, 514 insertions, 501 deletions
diff --git a/doc/wydawca.texi b/doc/wydawca.texi
index a136fd6..04b599f 100644
--- a/doc/wydawca.texi
+++ b/doc/wydawca.texi
@@ -92,7 +92,7 @@ How to Configure @command{wydawca}.
* Syntax:: Configuration file syntax.
* syslog::
* sql::
-* access methods::
+* dictionaries::
* archivation::
* spool::
* statistics::
@@ -105,13 +105,13 @@ Configuration file syntax
* Statements::
* Preprocessor::
-Access Methods
+Dictionaries
* sql type::
* builtin type::
* external type::
-SQL Access Methods
+SQL Dictionary
* project-owner-sql::
* project-uploader-sql::
@@ -130,13 +130,13 @@ Mail Notification
@chapter Introduction to Wydawca
@cindex introduction
Let's begin with a short synopsis. Suppose you run a developer's
-site, like, e.g. @indicateurl{gnu.org}. You have at least two
+site, like, e.g. @indicateurl{gnu.org}. You have two
@dfn{distribution @acronym{URL}s}: @indicateurl{ftp.gnu.org}, which
distributes stable versions of the software, and
@indicateurl{alpha.gnu.org}, which distributes alpha and pre-test
-versions. Now, package maintainers should have a way of uploading
-their packages to one of these sites. The currently accepted scheme
-is described in
+versions. Now, package maintainers need to have a way of uploading
+their packages to one of these sites. This is done using the
+@dfn{Automated FTP Upload} method, as described in
@ifnothtml
@ref{Automated FTP Uploads, Automated FTP Uploads, Automated FTP
Uploads, maintain, Information for maintainers of GNU software}.
@@ -157,16 +157,17 @@ corresponding to a certain distribution @acronym{URL}. For example,
@item @file{/incoming/ftp} @tab @indicateurl{ftp.gnu.org}
@item @file{/incoming/alpha} @tab @indicateurl{alpha.gnu.org}
@end multitable
+@*
@cindex @acronym{PGP}
@cindex detached signature
@cindex signature, detached
- Now, if the maintainer of the project @samp{foo} wishes to make a release
+ Now, if maintainer of the project @samp{foo} wishes to make a release
of the stable version @file{foo-1.0.tar.gz}, he first creates a detached
signature @file{foo-1.0.tar.gz.sig}. Then he creates a special
-@dfn{directive} file, that contains information about where the
+@dfn{directive} file, which contains information about where the
distributed tarball must be placed, and clear-signs it using his
-@acronym{PGP} key, thus obtaining file
+@acronym{PGP} key, thus obtaining the file
@file{foo-1.0.tar.gz.directive.asc}. Finally, he uploads these three files
(a @dfn{triplet}) to the upload site, storing them into the directory
@file{/incoming/ftp}.
@@ -179,9 +180,9 @@ their distribution sites.
@command{Wydawca} is such a release submission daemon. It is able to
handle any number of @samp{source/destination} pairs (called
-@dfn{spools}, offers an extensible logging and mail notification
-mechanism, allowing both package maintainers and site administrators
-to be immediately notified about any occurring problems.
+@dfn{spools}) in real time, and offers an extensible logging and mail
+notification mechanism, allowing both package maintainers and site
+administrators to be immediately notified about any occurring problems.
@command{Wydawca} supports version 1.1 of directory file, as
described in
@@ -224,7 +225,7 @@ that case.
upload and corresponding distribution directories. In
@command{wydawca} terminology, upload directories are also called
@dfn{source}, and distribution directories -- @dfn{destination}
-directories. The file also supplies all the information
+directories. The configuration file also supplies all the information
necessary to access user and project databases.
When started, @command{wydawca} scans each source directory and
@@ -235,9 +236,9 @@ supplied with each upload and that contains directive regarding the
placement of the uploaded files. A @dfn{triplet} is a standard
entity, consisting of three files: a clear-signed directive file, a
file to be distributed, and a detached signature of the latter.
-In some special cases, a clear-signed directive file alone is valid,
-namely when it contains only @dfn{standalone directives}, as described
-in
+In some special cases, a clear-signed directive file alone is valid.
+This happens when it contains only @dfn{standalone directives}, as
+described in
@ifnothtml
@ref{FTP Upload Directive File - v1.1,
Standalone directives, Standalone directives,
@@ -248,26 +249,38 @@ maintain, Information for maintainers of GNU software}.
Standalone directives}.
@end ifhtml
- Each @dfn{incomplete} triplet, i.e. such that misses one or more
+@cindex triplet, incomplete
+@cindex incomplete triplet
+@cindex triplet, expired
+@cindex expired triplet
+ Each @dfn{incomplete} triplet, i.e. a triplet missing one or more
necessary files, is then verified by checking if the modification
date of its oldest file is older than a predefined amount of time
-(@FIXME-pxref{file-sweep-time}), and if so, all files from this triplet are
-removed (an @dfn{expired triplet}). This gives users the possibility
-to restart interrupted or otherwise broken uploads later.
-
- Then, the utility ensures that each of the remaining triplets is
-created by a single person. Any triplets that do not are immediately
-removed.
+(@FIXME-pxref{file-sweep-time}). If so, the triplet is considered
+@dfn{expired}, and all its files are removed. This gives users the
+possibility to restart interrupted or otherwise broken uploads later.
+@cindex dictionary
@cindex @acronym{PGP}
+ After completing these preliminary stages, @command{wydawca}
+analyzes the directive file and extracts the project name
+from it. Using this name as a key, it looks up in the @dfn{project
+dictionary} a list of users authorized to make uploads for this
+project. This list contains user names and their corresponding public
+@acronym{PGP} keys. @command{Wydawca} tries to verify the directive
+file using each @acronym{PGP} key from this list, until a matching
+key is found, or the list in exhausted. In the latter case, the
+triplet is rejected. Otherwise, the key and its owner are remembered
+for the next step.
+
+@cindex detached signature
@cindex detached signature
@cindex signature, detached
- Then, @acronym{PGP} signatures of directive files and any detached
-signatures (if available) are verified. If they do not match public
-keys of the user who uploaded the triplet, such a triplet is
-discarded.
+ In this step, the uploaded file and its detached signature
+are verified. If they do not match the public key obtained in the
+previous step, the triplet is rejected.
- Finally, the directives from each directive file are executed. On
+ Finally, directives from the directive file are executed. On
this stage of the processing, the uploaded files are actually moved to
their destination directories, requested symbolic links are created,
etc.
@@ -387,7 +400,7 @@ directives any time by running @command{wydawca --config-help}.
* Syntax:: Configuration file syntax.
* syslog::
* sql::
-* access methods::
+* dictionaries::
* archivation::
* spool::
* statistics::
@@ -860,7 +873,7 @@ sql @var{id} @{
Here, @var{id} is a string uniquely identifying this
database. It is used by another configuration statements (e.g. by
-access methods, see the next section) to refer to this
+dictionaries, see the next section) to refer to this
database.
@end deffn
@@ -904,21 +917,21 @@ sql default @{
@end group
@end smallexample
-@node access methods
-@section Access Methods
-@cindex Access method
+@node dictionaries
+@section Dictionaries
+@cindex dictionaries
@cindex @acronym{PGP} key
-
-An @dfn{access method} defines the ways to retrieve user information
+@UNREVISED
+A @dfn{dictionary} defines the ways to retrieve user information
necessary to verify the submission. This information can be, for
example, the user's @acronym{PGP} key or his permissions on a project.
- Access methods are defined in configuration file using the
+ Dictionary is defined in configuration file using the
following syntax:
-@deffn {Config} access-method
+@deffn {Config} dictionary
@smallexample
-access-method @var{method-name} @{
+dictionary @var{dict-id} @{
type @var{type};
query @var{string};
params (@var{param1},@var{param2},...);
@@ -926,14 +939,14 @@ access-method @var{method-name} @{
@end smallexample
@end deffn
- Access method statements can appear either in the global scope of
+ A @code{dictionary} statement can appear either in the global scope of
the configuration file, or inside a @code{spool} statement
(@pxref{spool}). Global definitions affect all directory
pairs in the configuration file, and ones inside a @code{directory}
statement override them for that particular directory pair.
-There are two access methods, identified by the value of
-@var{method-name} tag:
+There are two dictionaries, identified by the value of
+@var{dict-id} tag:
@table @asis
@kwindex project-owner
@@ -949,10 +962,10 @@ order.
the users that are allowed to make uploads for the project.
@end table
-The sub-statements of @code{access-method} are:
+The sub-statements of @code{dictionary} are:
-@deffn {Config: access-method} type @var{name}
-Defines the type of this method. @var{Name} is one of the following:
+@deffn {Config: dictionary} type @var{name}
+Defines the type of this dictionary. @var{Name} is one of the following:
@table @asis
@kwindex builtin
@@ -966,14 +979,14 @@ Defines the type of this method. @var{Name} is one of the following:
@kwindex external
@item external
- Retrieve data using an external program. This method is reserved for
-future use.
+ Retrieve data using an external program. This dictionary type is
+reserved for future use.
@end table
-See below for a detailed description of these access methods.
+See below for a detailed description of these dictionary types.
@end deffn
-@deffn {Config: access-method} query @var{string}
+@deffn {Config: dictionary} query @var{string}
Sets the query used for retrieving the data. The @var{string} is
subject to meta-variable interpretation (@pxref{meta-interpretation}). The
following meta-variables are defined:
@@ -1012,12 +1025,12 @@ Spool source directory (@pxref{spool, source}).
@itemx user
@itemx user:name
The system name of the user that submitted the triplet. This is
-defined only in @samp{project-owner} access method.
+defined only for @samp{project-owner} dictionaries.
@end table
@end deffn
-@deffn {Config: access-method} params (@var{param1}, @var{param2}, ...)
-Supplies additional parameters for the method.
+@deffn {Config: dictionary} params (@var{param1}, @var{param2}, ...)
+Supplies additional parameters.
@end deffn
@menu
@@ -1027,9 +1040,9 @@ Supplies additional parameters for the method.
@end menu
@node sql type
-@subsection SQL Access Methods
-@cindex sql access type
-Access methods of @samp{sql} type retrieve information from an
+@subsection SQL Dictionary
+@cindex sql dictionary
+Dictionaries of @samp{sql} type retrieve information from an
@acronym{SQL} database (as of version @value{VERSION}, only
@samp{MySQL} databases are supported).
@@ -1042,8 +1055,7 @@ which determines database name and user credentials needed to access it.
@cindex Savane
The following sub-nodes contain sample definitions for the
-access methods using the @code{sql} type. They are based
-on the database structure used in
+@code{sql} dictionaries. They are based on the database structure used in
@uref{http://gna.org/projects/savane, @command{Savane} system}.
@menu
@@ -1059,7 +1071,7 @@ on the database structure used in
consisting of two columns: an email address and a user name, in this order.
@smallexample
-access-method project-owner @{
+dictionary project-owner @{
type sql;
params (default);
query "SELECT user.email, user.realname "
@@ -1077,7 +1089,7 @@ access-method project-owner @{
@UNREVISED
@smallexample
-access-method project-owner @{
+dictionary project-owner @{
type sql;
params (default);
query "SELECT user.email, user.realname "
@@ -1090,15 +1102,15 @@ access-method project-owner @{
@end smallexample
@node builtin type
-@subsection Built-in access methods
-@cindex builtin access type
+@subsection Built-in Dictionary
+@cindex builtin dictionary
@WRITEME
@node external type
-@subsection External access methods
-@cindex external access type
+@subsection External Dictionary
+@cindex external dictionary
-As of version @value{VERSION} this access type is not yet
+As of version @value{VERSION} this dictionary is not yet
implemented.
@node archivation
@@ -1275,7 +1287,7 @@ archive-signatures no;
A @dfn{distribution spool} defines the location of the source directory
and the corresponding distribution (or @dfn{destination})
directory. It may also set archivation type,
-various access methods and notifications for that directory, thus overriding
+various dictionaries and notifications for that directory, thus overriding
global settings.
Distribution spool is defined in the configuration file by the
@@ -1289,7 +1301,7 @@ spool @var{tag} @{
source @var{dir};
destination @var{dir};
file-sweep-time @var{interval};
- access-method @{ @dots{} @}
+ dictionary @{ @dots{} @}
archive @{ @dots{} @}
notify-event @{ @dots{} @}
@}
@@ -1338,9 +1350,9 @@ Configure spool-specific archivation. @xref{archivation}, for its
description.
@end deffn
-@deffn {Config: spool} access-method @var{tag} @{ @dots{} @}
-Configure spool-specific access-method. @xref{access
-methods}, for a detailed discussion of this statement.
+@deffn {Config: spool} dictionary @var{tag} @{ @dots{} @}
+Configure spool-specific dictionary. @xref{dictionaries}, for a
+detailed discussion of this statement.
@end deffn
@deffn {Config: spool} notify-event @{ @dots{} @}
@@ -1364,7 +1376,7 @@ spool ftp @{
@end smallexample
@noindent
-This spool defines no particular archivation type, access method or
+This spool defines no particular archivation type, dictionary or
notifications, so it will inherit these settings from the global
configuration.
@@ -1885,13 +1897,12 @@ The system administrator, as defined in @code{admin-address} statement
@kwindex owner
@item owner
Administrators of the project for which the files where
-uploaded. Their addresses are retrieved using the @samp{project-owner}
-access method (@pxref{access methods}).
+uploaded. Their addresses are retrieved from the @samp{project-owner}
+dictionary (@pxref{dictionaries}).
@kwindex user
@item user
-The user who uploaded files. The user address is returned by
-@samp{user-data} access method (@pxref{access methods}).
+The user who uploaded files.
@end table
@end deffn
@@ -2202,15 +2213,15 @@ notify-event @{
message @var{text-or-id:@i{<string>}};
@}
-# Define access method
-access-method @var{ident} @{
- # Method type
+# Define a dictionary
+dictionary @var{ident} @{
+ # Dictionary type
type @var{type:@i{<string>}};
# Query template
query @var{string:@i{<string>}};
- # Set method parameters
+ # Set dictionary parameters
params @var{arg:@i{<list of string>}};
@}
@@ -2231,15 +2242,15 @@ spool @var{tag:@i{<string>}} @{
# Define file sweep time
file-sweep-time @var{interval:@i{<string>}};
- # Define access method
- access-method @var{ident} @{
- # Method type
+ # Define a dictionary
+ dictionary @var{ident} @{
+ # Dictionary type
type @var{type:@i{<string>}};
# Query template
query @var{string:@i{<string>}};
- # Set method parameters
+ # Set dictionary parameters
params @var{arg:@i{<list of string>}};
@}
diff --git a/src/Makefile.am b/src/Makefile.am
index c96fbcb..a599118 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -20,6 +20,7 @@ wydawca_SOURCES=\
builtin.h\
cmdline.h\
config.c\
+ dictionary.c\
directive.c\
diskio.c\
exec.c\
@@ -28,7 +29,6 @@ wydawca_SOURCES=\
job.c\
lock.c\
meta.c\
- method.c\
net.c\
pidfile.c\
process.c\
diff --git a/src/builtin.c b/src/builtin.c
index 73b1d23..5588fd6 100644
--- a/src/builtin.c
+++ b/src/builtin.c
@@ -20,21 +20,21 @@
#include "regex.h"
int
-builtin_init (struct access_method *meth)
+builtin_init (struct dictionary *dict)
{
return 0;
}
int
-builtin_done (struct access_method *meth)
+builtin_done (struct dictionary *dict)
{
return 0;
}
void *
-builtin_open (struct access_method *meth)
+builtin_open (struct dictionary *dict)
{
- return meth;
+ return dict;
}
#define CMP_EXACT 0
@@ -159,7 +159,7 @@ static int default_ncol[] = {
};
int
-builtin_run (struct access_method *meth, void *handle, const char *req)
+builtin_lookup (struct dictionary *dict, void *handle, const char *req)
{
int i;
int rc;
@@ -168,19 +168,19 @@ builtin_run (struct access_method *meth, void *handle, const char *req)
int flags = 0;
strcmp_fn cmpfn = cmp_exact;
struct builtin_data_storage *bds;
- int ncol = default_ncol[meth->id];
+ int ncol = default_ncol[dict->id];
- if (meth->parmc == 0)
+ if (dict->parmc == 0)
{
- meth->nrow = meth->ncol = 0;
+ dict->nrow = dict->ncol = 0;
return 0;
}
obstack_init (&stk);
- for (i = 0; i < meth->parmc; i++)
+ for (i = 0; i < dict->parmc; i++)
{
- char *pat = meth->parmv[i];
+ char *pat = dict->parmv[i];
if (pat[0] == '/')
{
@@ -189,7 +189,7 @@ builtin_run (struct access_method *meth, void *handle, const char *req)
continue;
}
- if (i + ncol >= meth->parmc)
+ if (i + ncol >= dict->parmc)
break;
if (cmpfn (pat, req, flags))
@@ -197,7 +197,7 @@ builtin_run (struct access_method *meth, void *handle, const char *req)
size_t j;
for (j = 1; j <= ncol; j++)
{
- char *val = meth->parmv[i + j];
+ char *val = dict->parmv[i + j];
obstack_grow (&stk, val, strlen (val) + 1);
}
count++;
@@ -206,8 +206,8 @@ builtin_run (struct access_method *meth, void *handle, const char *req)
i += ncol;
}
- meth->nrow = count;
- meth->ncol = ncol;
+ dict->nrow = count;
+ dict->ncol = ncol;
if (count == 0)
{
@@ -234,32 +234,32 @@ builtin_run (struct access_method *meth, void *handle, const char *req)
rc = 0;
}
- meth->storage = bds;
+ dict->storage = bds;
return rc;
}
int
-builtin_free_result (struct access_method *method, void *handle)
+builtin_free_result (struct dictionary *dict, void *handle)
{
- if (method->storage)
+ if (dict->storage)
{
- struct builtin_data_storage *bds = method->storage;
+ struct builtin_data_storage *bds = dict->storage;
obstack_free (&bds->stk, NULL);
free (bds->wp);
free (bds);
- method->storage = NULL;
+ dict->storage = NULL;
}
return 0;
}
int
-builtin_get (struct access_method *method, void *handle,
+builtin_get (struct dictionary *dict, void *handle,
unsigned nrow, unsigned ncol)
{
- struct builtin_data_storage *bds = method->storage;
- char *str = bds->wp[nrow * method->ncol + ncol];
- method_copy_result (method, str, strlen (str));
+ struct builtin_data_storage *bds = dict->storage;
+ char *str = bds->wp[nrow * dict->ncol + ncol];
+ dictionary_copy_result (dict, str, strlen (str));
return 0;
}
diff --git a/src/builtin.h b/src/builtin.h
index 500a6cb..dd52bce 100644
--- a/src/builtin.h
+++ b/src/builtin.h
@@ -14,9 +14,9 @@
You should have received a copy of the GNU General Public License along
with this program. If not, see <http://www.gnu.org/licenses/>. */
-int builtin_init (struct access_method *);
-int builtin_done (struct access_method *);
-void *builtin_open (struct access_method *);
-int builtin_get (struct access_method *, void *, unsigned, unsigned);
-int builtin_run (struct access_method *, void *, const char *);
-int builtin_free_result (struct access_method *, void *);
+int builtin_init (struct dictionary *);
+int builtin_done (struct dictionary *);
+void *builtin_open (struct dictionary *);
+int builtin_get (struct dictionary *, void *, unsigned, unsigned);
+int builtin_lookup (struct dictionary *, void *, const char *);
+int builtin_free_result (struct dictionary *, void *);
diff --git a/src/config.c b/src/config.c
index f0a7042..15c191c 100644
--- a/src/config.c
+++ b/src/config.c
@@ -26,7 +26,7 @@ static struct archive_descr default_archive_descr = {
no_backups
};
-static struct access_method *default_access_method[access_method_count];
+static struct dictionary *default_dictionary[dictionary_count];
static struct notification *default_notification = NULL;
@@ -953,44 +953,44 @@ cb_notify_event (enum grecs_callback_command cmd,
-static enum access_method_type
-string_to_access_method_type (const char *str)
+static enum dictionary_type
+string_to_dictionary_type (const char *str)
{
if (strcmp (str, "sql") == 0)
- return method_sql;
+ return dictionary_sql;
else if (strcmp (str, "builtin") == 0)
- return method_builtin;
+ return dictionary_builtin;
else if (strcmp (str, "external") == 0)
- return method_external;
+ return dictionary_external;
else
- return method_none;
+ return dictionary_none;
}
static int
-cb_access_method_type (enum grecs_callback_command cmd,
+cb_dictionary_type (enum grecs_callback_command cmd,
grecs_locus_t *locus,
void *varptr,
grecs_value_t *value,
void *cb_data)
{
- enum access_method_type *ptype = varptr;
+ enum dictionary_type *ptype = varptr;
if (assert_string_arg (locus, cmd, value))
return 1;
- *ptype = string_to_access_method_type (value->v.string);
- if (*ptype == method_none)
- grecs_error (locus, 0, _("unknown access method: %s"), value->v.string);
+ *ptype = string_to_dictionary_type (value->v.string);
+ if (*ptype == dictionary_none)
+ grecs_error (locus, 0, _("unknown dictionary type: %s"), value->v.string);
return 0;
}
static int
-cb_access_method_params (enum grecs_callback_command cmd,
+cb_dictionary_params (enum grecs_callback_command cmd,
grecs_locus_t *locus,
void *varptr,
grecs_value_t *value,
void *cb_data)
{
- struct access_method *meth = varptr;
+ struct dictionary *meth = varptr;
size_t size;
if (cmd != grecs_callback_set_value)
@@ -1034,21 +1034,21 @@ cb_access_method_params (enum grecs_callback_command cmd,
return 0;
}
-static struct grecs_keyword access_method_kw[] = {
- { "type", N_("type"), N_("Method type"),
- grecs_type_string, NULL, offsetof(struct access_method, type),
- cb_access_method_type },
+static struct grecs_keyword dictionary_kw[] = {
+ { "type", N_("type"), N_("Dictionary type"),
+ grecs_type_string, NULL, offsetof(struct dictionary, type),
+ cb_dictionary_type },
{ "query", N_("string"), N_("Query template"),
- grecs_type_string, NULL, offsetof(struct access_method, query) },
- { "params", N_("arg"), N_("Set method parameters"),
+ grecs_type_string, NULL, offsetof(struct dictionary, query) },
+ { "params", N_("arg"), N_("Set dictionary parameters"),
grecs_type_string|GRECS_LIST, NULL, 0,
- cb_access_method_params },
+ cb_dictionary_params },
{ NULL }
};
int
-string_to_access_method_id (grecs_locus_t *locus,
- const char *str, enum access_method_id *idp)
+string_to_dictionary_id (grecs_locus_t *locus,
+ const char *str, enum dictionary_id *idp)
{
static const char *id_str[] = {
"project-uploader",
@@ -1056,13 +1056,13 @@ string_to_access_method_id (grecs_locus_t *locus,
NULL
};
static int id_num[] = {
- project_uploader_method,
- project_owner_method
+ project_uploader_dict,
+ project_owner_dict
};
ARGMATCH_VERIFY (id_str, id_num);
int rc, res;
- rc = string_to ("access method", str,
+ rc = string_to ("dictionary", str,
id_str, id_num,
&res,
locus);
@@ -1071,15 +1071,15 @@ string_to_access_method_id (grecs_locus_t *locus,
}
static int
-cb_access_method (enum grecs_callback_command cmd,
- grecs_locus_t *locus,
- void *varptr,
- grecs_value_t *value,
- void *cb_data)
+cb_dictionary (enum grecs_callback_command cmd,
+ grecs_locus_t *locus,
+ void *varptr,
+ grecs_value_t *value,
+ void *cb_data)
{
- struct access_method **pmeth, *meth;
+ struct dictionary **pmeth, *meth;
void **pdata = cb_data;
- enum access_method_id id;
+ enum dictionary_id id;
switch (cmd) {
case grecs_callback_section_begin:
@@ -1088,10 +1088,10 @@ cb_access_method (enum grecs_callback_command cmd,
grecs_error(locus, 0, _("tag must be a string"));
return 0;
}
- if (string_to_access_method_id (locus, value->v.string, &id))
+ if (string_to_dictionary_id (locus, value->v.string, &id))
return 1;
- pmeth = (struct access_method **) varptr + id;
- *pmeth = method_new (id, method_builtin);
+ pmeth = (struct dictionary **) varptr + id;
+ *pmeth = dictionary_new (id, dictionary_builtin);
*pdata = *pmeth;
break;
@@ -1099,17 +1099,17 @@ cb_access_method (enum grecs_callback_command cmd,
meth = *pdata;
switch (meth->type)
{
- case method_sql:
+ case dictionary_sql:
if (meth->parmc == 0 || !meth->parmv[0])
{
grecs_error (locus, 0, _("SQL connection is not declared"));
- meth->type = method_none;
+ meth->type = dictionary_none;
}
else if (!sql_connection_exists_p (meth->parmv[0]))
{
grecs_error (locus, 0, _("SQL connection `%s' not declared"),
meth->parmv[0]);
- meth->type = method_none;
+ meth->type = dictionary_none;
}
break;
@@ -1171,9 +1171,9 @@ static struct grecs_keyword spool_kw[] = {
{ "file-sweep-time", N_("interval"), N_("Define file sweep time"),
grecs_type_string, NULL, offsetof(struct spool, file_sweep_time),
cb_interval },
- { "access-method", N_("ident"), N_("Define access method"),
- grecs_type_section, NULL, offsetof(struct spool, access_method),
- cb_access_method, NULL, access_method_kw },
+ { "dictionary", N_("ident"), N_("Define data dictionary"),
+ grecs_type_section, NULL, offsetof(struct spool, dictionary),
+ cb_dictionary, NULL, dictionary_kw },
{ "archive", N_("type: string"), N_("Set up archivation"),
grecs_type_section, NULL, offsetof(struct spool, archive),
cb_archive, NULL, archive_kw },
@@ -1208,8 +1208,8 @@ cb_spool (enum grecs_callback_command cmd,
spool = xzalloc (sizeof (*spool));
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];
+ for (i = 0; i < NITEMS (spool->dictionary); i++)
+ spool->dictionary[i] = default_dictionary[i];
spool->archive = default_archive_descr;
*pdata = spool;
break;
@@ -1247,11 +1247,11 @@ cb_spool (enum grecs_callback_command cmd,
&& spool->vtab.test_url (spool->dest_url, locus))
rc = 1;
- for (i = 0; i < access_method_count; i++)
- if (spool->access_method[i]->type == method_external)
+ for (i = 0; i < dictionary_count; i++)
+ if (spool->dictionary[i]->type == dictionary_external)
{
grecs_error (locus, 0,
- _("Sorry, method type `external' is not yet supported"));
+ _("Sorry, the dictionary type `external' is not yet supported"));
rc = 1;
}
@@ -1452,9 +1452,9 @@ static struct grecs_keyword wydawca_kw[] = {
grecs_type_section, &default_notification, 0,
cb_notify_event, NULL, notify_event_kw },
- { "access-method", N_("ident"), N_("Define access method"),
- grecs_type_section, default_access_method, 0,
- cb_access_method, NULL, access_method_kw },
+ { "dictionary", N_("ident"), N_("Define data dictionary"),
+ grecs_type_section, default_dictionary, 0,
+ cb_dictionary, NULL, dictionary_kw },
{ "spool", N_("tag: string"), N_("Define distribution spool"),
grecs_type_section, NULL, 0,
@@ -1495,6 +1495,6 @@ config_init()
if (serv != NULL)
grecs_default_port = serv->s_port;
- for (i = 0; i < access_method_count; i++)
- default_access_method[i] = method_new (i, method_builtin);
+ for (i = 0; i < dictionary_count; i++)
+ default_dictionary[i] = dictionary_new (i, dictionary_builtin);
}
diff --git a/src/dictionary.c b/src/dictionary.c
new file mode 100644
index 0000000..c31baf8
--- /dev/null
+++ b/src/dictionary.c
@@ -0,0 +1,228 @@
+/* wydawca - automatic release submission daemon
+ Copyright (C) 2007 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 <http://www.gnu.org/licenses/>. */
+
+#include "wydawca.h"
+#include "sql.h"
+#include "builtin.h"
+
+struct dictionary_descr
+{
+ const char *name;
+
+ int (*init) (struct dictionary *);
+ int (*done) (struct dictionary *);
+ int (*free) (struct dictionary *, void *);
+
+ void *(*open) (struct dictionary *);
+ int (*close) (struct dictionary *, void *);
+
+ int (*get) (struct dictionary *, void *, unsigned, unsigned);
+ int (*lookup) (struct dictionary *, void *, const char *);
+ int (*quote) (struct dictionary *, void *, const char *, char **, size_t *);
+};
+
+static struct dictionary_descr dictionary_tab[] = {
+ { "none", NULL, NULL, NULL, NULL, NULL, NULL, NULL },
+ { "sql", sql_init_dictionary, sql_done_dictionary, sql_free_result,
+ sql_open, NULL, sql_get_dictionary, sql_lookup_dictionary, sql_quote },
+ { "builtin", builtin_init, builtin_done, builtin_free_result,
+ builtin_open, NULL,
+ builtin_get,
+ builtin_lookup },
+ { "external", NULL, NULL, NULL, NULL, NULL, NULL, NULL }
+};
+
+struct dictionary *
+dictionary_new (enum dictionary_id id, enum dictionary_type type)
+{
+ struct dictionary *mp = xmalloc (sizeof mp[0]);
+ memset (mp, 0, sizeof mp[0]);
+ mp->id = id;
+ mp->type = type;
+ return mp;
+}
+
+int
+dictionary_init (struct dictionary *dict)
+{
+ struct dictionary_descr *mp = dictionary_tab + dict->type;
+ int rc = 0;
+
+ if (dict->init_passed++)
+ return 0;
+ if (debug_level > 1)
+ {
+ int i;
+ logmsg (LOG_DEBUG, _("initializing dictionary: %s \"%s\""),
+ mp->name, SP (dict->query));
+ for (i = 0; i < dict->parmc; i++)
+ logmsg (LOG_DEBUG, " parmv[%d]=%s", i, dict->parmv[i]);
+ }
+ if (mp->init)
+ rc = mp->init (dict);
+ if (rc == 0)
+ dict->init_passed = 1;
+ return rc;
+}
+
+void *
+dictionary_open (struct dictionary *dict)
+{
+ struct dictionary_descr *mp = dictionary_tab + dict->type;
+
+ if (!mp->open)
+ return NULL;
+ return mp->open (dict);
+}
+
+int
+dictionary_close (struct dictionary *dict, void *handle)
+{
+ struct dictionary_descr *mp = dictionary_tab + dict->type;
+ if (!mp->close)
+ return 0;
+ return mp->close (dict, handle);
+}
+
+int
+dictionary_done (struct dictionary *dict)
+{
+ struct dictionary_descr *mp = dictionary_tab + dict->type;
+ int rc = 0;
+
+ if (dict->init_passed == 0)
+ return 0;
+ if (--dict->init_passed)
+ return 0;
+ if (debug_level > 1)
+ {
+ int i;
+ logmsg (LO