summaryrefslogtreecommitdiffabout
authorSergey Poznyakoff <gray@gnu.org>2019-07-24 11:14:47 (GMT)
committer Sergey Poznyakoff <gray@gnu.org>2019-07-24 11:27:11 (GMT)
commitc047ed856d6d23137ef1df01c1297db36bad3f8c (patch) (side-by-side diff)
tree1999db947cb5e38df8a85d314daa0eef7c7624d0
parent07ea006a31def46ba6ea936dbea366219152d9b6 (diff)
downloadwydawca-master.tar.gz
wydawca-master.tar.bz2
Use wordsplit to expand variables in strings.HEADmaster
* NEWS: Raise version number. * configure.ac: Link wydawca.h to include/wydawca Raise version number * doc/wydawca.texi: Document changes. * etc/wydawca.rc: Fix the syntax. * grecs: Upgrace. * include/wydawca/wydawca.h (wy_vlog): New proto. (wy_log, wy_dbg): Format is const char *. (wy_triplet_t): Change typedef. (wy_metadef): Remove struct. (wy_vardef): New struct. (wy_triplet_expand_param) (wy_expand_copy): New protos. * modules/logstat/mod_logstat.c: Update. * modules/mailutils/Makefile.am (AM_CPPFLAGS): Modify, * modules/mailutils/mod_mailutils.c: Update. * src/Makefile.am (wydawca_SOURCES): Remove meta.c * src/dictionary.c: Fix comment. * src/directive.c (directive_get_value): Triplet pointer is const. * src/meta.c: Remove. * src/timer.c: (timer_fill_meta) (timer_free_meta): Remove. * src/triplet.c: Use wordsplit for expansions. * src/wydawca.c (wy_vlog): New function. (wy_stat_expansion): New function. * src/wydawca.h: Remove metadef protos. * tests/etc/notify.rcin: Update variable reference syntax.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--NEWS57
-rw-r--r--configure.ac3
-rw-r--r--doc/wydawca.texi156
-rw-r--r--etc/wydawca.rc25
m---------grecs0
-rw-r--r--include/wydawca/wydawca.h30
-rw-r--r--modules/logstat/mod_logstat.c4
-rw-r--r--modules/mailutils/Makefile.am1
-rw-r--r--modules/mailutils/mod_mailutils.c64
-rw-r--r--src/Makefile.am1
-rw-r--r--src/dictionary.c2
-rw-r--r--src/directive.c2
-rw-r--r--src/meta.c191
-rw-r--r--src/timer.c52
-rw-r--r--src/triplet.c603
-rw-r--r--src/wydawca.c54
-rw-r--r--src/wydawca.h15
-rw-r--r--tests/etc/notify.rcin16
18 files changed, 615 insertions, 661 deletions
diff --git a/NEWS b/NEWS
index d99ce47..b73895b 100644
--- a/NEWS
+++ b/NEWS
@@ -1,7 +1,62 @@
-Wydawca NEWS -- history of user-visible changes. 2019-07-22
+Wydawca NEWS -- history of user-visible changes. 2019-07-24
See the end of file for copying conditions.
Please send Wydawca bug reports to <bug-wydawca@gnu.org.ua>.
+
+Version 3.0.90 (git)
+
+* Variable expansion syntax
+
+This release uses wordsplit v1.0-9-g7eaa3c4. Normal shell like
+expansion is allowed. This means that curly braces around variable
+names are optional and that the following forms are now allowed:
+
+${VARIABLE:-WORD}
+ "Use Default Values". If VARIABLE is unset or null, the
+ expansion of WORD is substituted. Otherwise, the value of
+ VARIABLE is substituted.
+
+${VARIABLE:=WORD}
+ "Assign Default Values". If VARIABLE is unset or null, the
+ expansion of WORD is assigned to variable. The value of
+ VARIABLE is then substituted.
+
+ The assigned value remains in effet during expansion of the
+ current string.
+
+${VARIABLE:?WORD}
+ "Display Error if Null or Unset". If VARIABLE is null or
+ unset, the expansion of WORD (or a message to that effect if
+ WORD is not present) is output to the current logging channel.
+ Otherwise, the value of VARIABLE is substituted.
+
+${VARIABLE:+WORD}
+ "Use Alternate Value". If VARIABLE is null or unset, nothing
+ is substituted, otherwise the expansion of WORD is
+ substituted.
+
+* Handling of undefined variables
+
+Attempt to expand undefined variable causes fatal error. Use one of
+the advanced forms described above to handle such cases gracefully.
+
+* Variable names
+
+Several variable names have changed. Names that contained dash,
+now use underscore instead. These are:
+
+ Old name Use this instead
+ ------------------- -------------------
+ stat:check-failures stat:check_failures
+ dest-dir dest_dir
+ source-dir source_dir
+ user:real-name user:real_name
+
+* $- is gone
+
+Trailing newlines are automatically removed from all variable
+expansions. Consequently, the $- marker (delete to the end of line)
+has been removed.
Version 3.0, 2019-07-22
diff --git a/configure.ac b/configure.ac
index 2eb680f..6a46de6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -15,7 +15,7 @@
# along with wydawca. If not, see <http://www.gnu.org/licenses/>.
AC_PREREQ(2.63)
-AC_INIT([wydawca], 3.0, [bug-wydawca@gnu.org.ua], [wydawca],
+AC_INIT([wydawca], 3.0.90, [bug-wydawca@gnu.org.ua], [wydawca],
[http://www.gnu.org.ua/software/wydawca])
AC_CONFIG_SRCDIR([src/wydawca.c])
AC_CONFIG_AUX_DIR([build-aux])
@@ -148,6 +148,7 @@ AM_CONDITIONAL([COND_INOTIFY],[test $status_inotify = yes])
GRECS_SETUP([grecs],[tree-api git2chg getopt tests shared install-headers
std-pp-setup])
+AC_CONFIG_LINKS(include/wydawca/wordsplit.h:grecs/wordsplit/wordsplit.h)
AH_BOTTOM([
#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
diff --git a/doc/wydawca.texi b/doc/wydawca.texi
index 2763b6d..8950987 100644
--- a/doc/wydawca.texi
+++ b/doc/wydawca.texi
@@ -728,52 +728,68 @@ example above:
@end group
@end smallexample
-@anchor{meta-interpretation}
-@cindex meta-interpretation
-@cindex meta-variables
-Depending on the context, the contents of a quoted string may be
-subject to @dfn{meta-variable interpretation}. During this process,
-any sequence
+@anchor{variable expansion}
+@cindex variable expansion
+@cindex variables
+Depending on the context, the quoted string may be subject to
+@dfn{variable expansion}.
-@smallexample
-$@{@var{var}@}
-@end smallexample
+During variable expansion, references to variables
+in the string are replaced with their actual values. A variable
+reference has two basic forms:
-@noindent
-where @var{var} is the name of a defined meta-variable, is replaced with
-the value of the variable. This sequence is called @dfn{meta-
-reference}. For example, if the meta-variable @samp{user} has the
-value @samp{smith}, then the string
-
-@smallexample
-"where user = '$@{user@}'"
-@end smallexample
+@example
+ $@var{v}
+ $@{@var{v}@}
+@end example
@noindent
-becomes
+where @var{v} is the variable name. The notation in curly braces
+serves several purposes. First, it should be used if the variable
+reference is immediately followed by an alphanumeric symbol, which
+will otherwise be considered part of it (as in @samp{$@{home@}dir}).
+Secondly, this form allows for specifying the action to take if the
+variable is undefined or expands to an empty value.
-@smallexample
-"where user = 'smith'"
-@end smallexample
-
-If the name of the variable consists of a single character, the curly
-braces around it may be omitted. Thus, @code{$@{u@}} and @code{$u} are
-equivalent.
+The following special forms are recognized:
-If @var{var} is not defined, the meta-reference is left unchanged.
+@table @asis
+@item $@{@var{variable}:-@var{word}@}
+@dfn{Use Default Values}. If @var{variable} is unset or null, the expansion
+of @var{word} is substituted. Otherwise, the value of @var{variable} is
+substituted.
+
+@item $@{@var{variable}:=@var{word}@}
+@dfn{Assign Default Values}. If @var{variable} is unset or null, the
+expansion of @var{word} is assigned to variable. The value of
+@var{variable} is then substituted.
+
+The assigned value remains in effet during expansion of the current string.
+
+@item $@{@var{variable}:?@var{word}@}
+@dfn{Display Error if Null or Unset}. If @var{variable} is null or unset,
+the expansion of @var{word} (or a message to that effect if @var{word} is
+not present) is output to the current logging channel. Otherwise, the
+value of @var{variable} is substituted.
+
+@item $@{@var{variable}:+@var{word}@}
+@dfn{Use Alternate Value}. If @var{variable} is null or unset, nothing is
+substituted, otherwise the expansion of @var{word} is substituted.
+@end table
-The special sequence @samp{$-} causes removal of it and any character
-following it. Most often it is used as a next-to-last character
-on a line, right before the newline. In this position it causes the
-removal of the trailing newline, similar to @samp{dnl} in @command{m4}.
-@xref{listings, Triplet Listings}, for a detailed description and
-examples of @samp{$-} use.
+These constructs test for a variable that is unset or null. Omitting
+the colon results in a test only for a variable that is unset.
-To insert a literal @samp{$} character in a string that is subject to
-meta-variable interpretation, duplicate it: @samp{$$}.
+@anchor{handling of undefined variables}
+@cindex expansion of undefined variables
+@cindex undefined variable, expansion
+If a string contains a reference to an undefined variable,
+@command{wydawca} will report an error and abort. To
+gracefully handle such cases, use the @dfn{default value construct},
+defined above.
-The exact set of defined meta-variables and their values depend on the
-context and are discussed in detail below.
+@FIXME{Implement the expand-undefined setting, similar to the one in
+rush}.
@anchor{here-document}
@item Here-document
@@ -1496,41 +1512,42 @@ See below for a detailed description of these dictionary types.
@anchor{query}
@deffn {Config: dictionary} query 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:
+subject to variable expansion (@pxref{variable expansion}). The
+following variables are defined in this context:
@table @code
-@kwindex p
@kwindex project
-@item p
-@itemx project
+@item project
The system name of the project for which the triplet is
submitted. It is defined as the value of directive
@code{directory}, or, in case this value contains slashes, the
shortest initial prefix of that value, not containing slashes.
+@kwindex spool
@item spool
The name of the distribution spool where this upload originates
(@pxref{spool}).
+@kwindex url
@item url
The @acronym{URL} of the spool, as set in the @code{url} statement
of the @code{spool} block (@pxref{spool, url}).
+@kwindex dir
@item dir
Directory (relative to the project distribution root) where the
files are going to be uploaded.
-@item dest-dir
+@kwindex dest_dir
+@item dest_dir
Spool destination directory (@pxref{spool, destination}).
-@item source-dir
+@kwindex source_dir
+@item source_dir
Spool source directory (@pxref{spool, source}).
-@kwindex u
@kwindex user
-@item u
-@itemx user
+@item user
@itemx user:name
The system name of the user that submitted the triplet. This is
defined only for @samp{project-owner} dictionaries.
@@ -2010,8 +2027,9 @@ spool @var{tag} @{
@end smallexample
The @var{tag} argument defines a unique identifier for this spool. It
-will be used in log messages, timers (@pxref{spool-timers}) and in
-meta-variable interpretation (@pxref{meta-interpretation}).
+will be used in log messages, timers (@pxref{spool-timers}) and is
+available for variable expansion (@pxref{variable expansion}) as the
+@samp{$spool} variable.
@end deffn
@deffn {Config: spool} alias list
@@ -2028,7 +2046,7 @@ description of this feature.
@deffn {Config: spool} url string
Defines download @acronym{URL}, associated with this spool. Its value
-may be used as @samp{$@{url@}} meta-variable in mail notifications.
+may be used as the variable @samp{$url} in mail notifications.
@end deffn
@deffn {Config: spool} source dir
@@ -2215,11 +2233,11 @@ notification}) is generated.
In case of non-zero return, the script may return additional
diagnostics on the standard output. This diagnostics will be
-available for use in notification messages via the @samp{check:diagn}
-meta-variable.
+available for use in notification messages via the @samp{$check:diagn}
+variable.
Additionally, the actual return code of the script, in decimal, is
-available in the @samp{check:result} meta-variable. If the script
+available in the @samp{$check:result} variable. If the script
terminates on a signal, the value of this variable is
@samp{SIG+@var{n}}, where @var{n} is the signal number.
@end deffn
@@ -2776,7 +2794,7 @@ mailer "|/bin/nullmail localhost -F$@{sender@} $@{rcpt@}"
@cindex notification message template
@cindex message template
Each notification message is build from a message template, by
-expanding meta-variables (@pxref{meta-interpretation}) within it.
+expanding variables (@pxref{variable expansion}) within it.
The message text may be specified either in place within the
configuration directive it belongs to (@pxref{notification}), or
defined by @code{define-message} statement.
@@ -2874,8 +2892,8 @@ the @acronym{GPG} home directory (@pxref{gpg-homedir}).
The statistics message is sent to addresses configured by
@code{admin-address} statement (@pxref{mod_mailutils, admin-address}).
-@cindex meta-variables in admin notifications
-The meta-variables available for use in statistics reports are:
+@cindex variables in admin notifications
+The variables available for use in statistics reports are:
@anchor{statistics variables}
@multitable @columnfractions 0.30 0.70
@@ -2912,7 +2930,7 @@ triplets.
@kwindex stat:rmsymlinks
@item stat:rmsymlinks @tab Number of symbolic links removed.
@kwindex stat:check-failures
-@item stat:check-failures @tab Number of verification failures
+@item stat:check_failures @tab Number of verification failures
(@pxref{verification}).
@end multitable
@@ -3060,9 +3078,9 @@ template, or a reference to a template previously defined by a
@kwindex dir
@item dir @tab Directory (relative to the project distribution
root) where the files where uploaded.
-@kwindex dest-dir
+@kwindex dest_dir
@item dest-dir @tab Value of the @code{destination} keyword.
-@kwindex source-dir
+@kwindex source_dir
@item source-dir @tab Value of the @code{source} keyword.
@kwindex triplet:dist
@item triplet:dist @tab File name of the main distribution file.
@@ -3082,7 +3100,7 @@ $@{triplet:ls:dir@}
@end smallexample
}.
@kwindex triplet:ls:upload
-@item triplet:upload @tab Listing of the uploaded files (see below).
+@item triplet:ls:upload @tab Listing of the uploaded files (see below).
@kwindex triplet:dist
@item triplet:ls:dist @tab Listing of the main distribution file (see below).
@kwindex triplet:ls:sig
@@ -3093,7 +3111,7 @@ $@{triplet:ls:dir@}
@item user @tab System name of the user who uploaded the triplet.
@kwindex user:name
@item user:name @tab System name of the user who uploaded the triplet.
-@kwindex user:real-name
+@kwindex user:real_name
@item user:real-name @tab Real name of the user who uploaded the triplet.
@kwindex user:email
@item user:email @tab Email of the user who uploaded the triplet.
@@ -3164,14 +3182,8 @@ example, here is a possible @code{$@{triplet:ls:full@}} listing:
-rw-r--r-- gray user 62 2007-09-06 22:14:35 tar-1.18.tar.gz.directive.asc
@end smallexample
- The following example shows how to configure success notification
-for the user. Notice the use of the @samp{$-} after
-@samp{$@{triplet:ls:upload@}}: it removes the newline character after
-it and thus allows for more natural indentation of the next
-line. Without it, the expanded message would have contained two
-newlines after the full listing: one produced by
-@samp{$@{triplet:ls:upload@}} and the second one taken verbatim from
-the message template.
+ The example in the following subsection shows how to configure
+success notification for the user.
@node mod_mailutils example
@subsubsection Example of mod_mailutils configuration
@@ -3208,7 +3220,7 @@ module-init mailutils @{
files archived ..................... $@{stat:archives@}
symlinks created ................... $@{stat:symlinks@}
symlinks removed ................... $@{stat:rmsymlinks@}
- verification failures .............. $@{stat:check-failures@}
+ verification failures .............. $@{stat:check_failures@}
Timings:
@@ -3247,7 +3259,7 @@ notify-event @{
Upload of $@{project@} to $@{url@}/$@{dir@} finished successfully.
Files uploaded:
- $@{triplet:ls:upload@}$-
+ $@{triplet:ls:upload@}
Resource usage: $@{timer:triplet:real@}/$@{timer:wydawca:real@}r \
$@{timer:triplet:user@}/$@{timer:wydawca:user@}u \
@@ -3324,7 +3336,7 @@ files uploaded: $@{stat:uploads@}
files archived: $@{stat:archives@}
symlinks created: $@{stat:symlinks@}
symlinks removed: $@{stat:rmsymlinks@}
-check failures: $@{stat:check-failures@}
+check failures: $@{stat:check_failures@}
EOT;
@end group
@end example
diff --git a/etc/wydawca.rc b/etc/wydawca.rc
index 22800b2..6790926 100644
--- a/etc/wydawca.rc
+++ b/etc/wydawca.rc
@@ -108,6 +108,7 @@ files uploaded ..................... ${stat:uploads}
files archived ..................... ${stat:archives}
symlinks created ................... ${stat:symlinks}
symlinks removed ................... ${stat:rmsymlinks}
+verification failures .............. ${stat:check_failures}
Regards,
Wydawca
@@ -125,7 +126,7 @@ Subject: Upload of ${project} successful
Upload of ${project} to ${dir} finished successfully. Files uploaded:
-${triplet:upload}$-
+${triplet:upload}
Regards,
Wydawca
@@ -140,10 +141,10 @@ notify-event {
To: ${email:owner}
Subject: Upload of ${project} successful
-${user:real-name} (${user:email}) successfully uploaded files
+${user:real_name} (${user:email}) successfully uploaded files
for ${project} to ${dir}. Files uploaded:
-${triplet:upload}$-
+${triplet:upload}
Regards,
Wydawca
@@ -163,10 +164,10 @@ Subject: Suspicious upload of ${project}
Someone not authorized to make releases for ${project}
has attempted to upload the following files to ${dir}:
-${triplet:full}$-
+${triplet:full}
This upload has been ignored and the files removed. The person who attempted
-the upload was ${user:real-name}, user name ${user:name}, email ${user:email}.
+the upload was ${user:real_name}, user name ${user:name}, email ${user:email}.
If you think this is an error and wish this user to be authorized to make
releases for ${project}, please contact <puszcza-hackers@gnu.org.ua>.
Otherwise, let us know so we could undertake appropriate measures.
@@ -186,11 +187,11 @@ notify-event {
To: ${email:owner}
Subject: Suspicious upload of ${project}
-${user:real-name} (${user:email}) has tried to make a release
+${user:real_name} (${user:email}) has tried to make a release
for ${project}. However, the signature of the directive file was wrong,
which looks suspicious. The person uploaded the following files:
-${triplet:full}$-
+${triplet:full}
This upload has been ignored and the files removed.
@@ -216,7 +217,7 @@ Someone (apparently you), has tried to make a release for ${project}.
However, the detached signature signature was wrong, which looks
suspicious. The person uploaded the following files:
-${triplet:full}$-
+${triplet:full}
This upload has been ignored and the files removed. If it was you who
attempted this upload, please make sure you use the right PGP key and
@@ -238,11 +239,11 @@ notify-event {
To: ${email:owner}
Subject: Suspicious upload of ${project}
-${user:real-name} (${user:email}) has tried to make a release
+${user:real_name} (${user:email}) has tried to make a release
for ${project}. However, the detached signature file was wrong,
which looks suspicious. The person uploaded the following files:
-${triplet:full}$-
+${triplet:full}
This upload has been ignored and the files removed.
@@ -263,12 +264,12 @@ notify-event {
To: ${email:user}
Cc: ${email:owner}
Subject: ${triplet:dist} rejected
-X-Wydawca-Uploader: "${user:real-name}" (${user:name}) <${user:email}>
+X-Wydawca-Uploader: "${user:real_name}" (${user:name}) <${user:email}>
Your upload of ${triplet:dist} has been rejected by the distribution
verification procedure with the following diagnostics:
-${check:diagn}$-
+${check:diagn}
Please fix the tarball and resubmit.
diff --git a/grecs b/grecs
-Subproject 79d50b4ab53f5ea4de6041a52edf938ec0e9c7f
+Subproject c518c214671b4563fa0a0baa0be60050b4f1540
diff --git a/include/wydawca/wydawca.h b/include/wydawca/wydawca.h
index 5af2996..a541157 100644
--- a/include/wydawca/wydawca.h
+++ b/include/wydawca/wydawca.h
@@ -40,8 +40,9 @@ extern char *wy_syslog_tag; /* Syslog tag */
# define WY_PRINTFLIKE(fmt,narg) __attribute__ ((__format__ (__printf__, fmt, narg)))
#endif
-void wy_log(int prio, char *fmt, ...) WY_PRINTFLIKE(2, 3);
-void wy_dbg(char *fmt, ...) WY_PRINTFLIKE(1, 2);
+void wy_log(int prio, char const *fmt, ...) WY_PRINTFLIKE(2, 3);
+void wy_vlog(int prio, char const *fmt, va_list ap);
+void wy_dbg(char const *fmt, ...) WY_PRINTFLIKE(1, 2);
#define wy_debug(l,c) do { \
if (wy_debug_level >= (l)) \
wy_dbg c; \
@@ -91,24 +92,21 @@ struct wy_user {
char *fpr;
};
-typedef struct wy_triplet *wy_triplet_t;
+typedef struct wy_triplet wy_triplet_t;
-const char *wy_triplet_project(wy_triplet_t trp);
-struct wy_user *wy_triplet_get_uploaders(wy_triplet_t trp);
-struct wy_user *wy_triplet_get_admins(wy_triplet_t trp);
-struct wy_user *wy_triplet_get_uploader(wy_triplet_t trp);
+const char *wy_triplet_project(wy_triplet_t *trp);
+struct wy_user *wy_triplet_get_uploaders(wy_triplet_t *trp);
+struct wy_user *wy_triplet_get_admins(wy_triplet_t *trp);
+struct wy_user *wy_triplet_get_uploader(wy_triplet_t *trp);
-struct wy_metadef {
- char *kw;
- char *value;
- const char *(*expand) (struct wy_metadef *, void *);
- char *storage;
- void *data;
+struct wy_vardef {
+ char const *name;
+ int (*expand)(char **ret, struct wy_triplet *trp);
};
+char *wy_triplet_expand_param(const char *tmpl, struct wy_triplet *trp,
+ struct wy_vardef *xmeta);
char *wy_expand_stats(const char *tmpl);
-char *wy_triplet_expand_param(const char *tmpl, struct wy_triplet const *trp,
- struct wy_metadef *xmeta);
-
int wy_stat_mask_p(unsigned long mask);
+int wy_expand_copy(char **ret, char const *s);
diff --git a/modules/logstat/mod_logstat.c b/modules/logstat/mod_logstat.c
index 02452e2..6a059c5 100644
--- a/modules/logstat/mod_logstat.c
+++ b/modules/logstat/mod_logstat.c
@@ -76,12 +76,12 @@ static char *default_log_message[] = {
"files archived: ${stat:archives}",
"symlinks created: ${stat:symlinks}",
"symlinks removed: ${stat:rmsymlinks}",
- "check failures: ${stat:check-failures}",
+ "check failures: ${stat:check_failures}",
NULL
};
void
-wy_notify(void *data, int ev, wy_triplet_t trp)
+wy_notify(void *data, int ev, wy_triplet_t const *trp)
{
struct grecs_list_entry *ep;
char *text;
diff --git a/modules/mailutils/Makefile.am b/modules/mailutils/Makefile.am
index f968f7b..81c6aad 100644
--- a/modules/mailutils/Makefile.am
+++ b/modules/mailutils/Makefile.am
@@ -8,5 +8,6 @@ AM_LDFLAGS = -module -avoid-version -no-undefined
AM_CPPFLAGS = \
-I$(top_srcdir)\
-I$(top_srcdir)/include\
+ -I$(top_builddir)/include\
-I$(top_builddir)/src\
@GRECS_INCLUDES@ @MAILUTILS_INCLUDES@
diff --git a/modules/mailutils/mod_mailutils.c b/modules/mailutils/mod_mailutils.c
index bbd34f0..577723a 100644
--- a/modules/mailutils/mod_mailutils.c
+++ b/modules/mailutils/mod_mailutils.c
@@ -22,6 +22,7 @@
#include <wydawca/wydawca.h>
#include <wydawca/cfg.h>
#include <mailutils/mailutils.h>
+#include <wydawca/wordsplit.h>
#define WY_MODULE mod_mailutils
@@ -617,7 +618,7 @@ wy_flush()
}
static mu_address_t
-get_uploader_email(wy_triplet_t trp, const char **errp)
+get_uploader_email(wy_triplet_t *trp, const char **errp)
{
struct wy_user const *info = wy_triplet_get_uploader(trp);
mu_address_t addr;
@@ -643,7 +644,7 @@ get_uploader_email(wy_triplet_t trp, const char **errp)
}
static mu_address_t
-get_owner_address(wy_triplet_t trp)
+get_owner_address(wy_triplet_t *trp)
{
struct wy_user *wp;
mu_address_t rcpt = NULL;
@@ -662,47 +663,60 @@ get_owner_address(wy_triplet_t trp)
return rcpt;
}
-static const char *
-expand_email_admin(struct wy_metadef *def, void *data)
+static int
+expand_email_admin(char **ret, struct wy_triplet *trp)
{
- if (mu_address_aget_printable(admin_address, &def->storage) == 0)
- def->value = def->storage;
- else
- def->value = "";
- return def->value;
+ int rc;
+ size_t size = 0;
+
+ rc = mu_address_aget_printable(admin_address, ret);
+ if (rc == 0)
+ return WRDSE_OK;
+ *ret = NULL;
+ if (grecs_asprintf(ret, &size, "mu_address_aget_printable: %s",
+ mu_strerror(rc)))
+ return WRDSE_NOSPACE;
+ return WRDSE_USERERR;
}
-static const char *
-expand_email_owner(struct wy_metadef *def, void *data)
+static int
+expand_email_owner(char **ret, struct wy_triplet *trp)
{
- wy_triplet_t trp = data;
mu_address_t addr;
-
+ int rc;
+
addr = get_owner_address(trp);
if (!addr) {
wy_log(LOG_ERR, _("cannot get email of the %s's owner"),
wy_triplet_project(trp));
- def->value = "";
+ return WRDSE_UNDEF;
} else {
- if (mu_address_aget_printable(addr, &def->storage) == 0)
- def->value = def->storage;
- else
- def->value = "";
+ rc = mu_address_aget_printable(addr, ret);
mu_address_destroy(&addr);
+ if (rc) {
+ size_t size = 0;
+ *ret = NULL;
+ if (grecs_asprintf(ret,
+ &size,
+ "mu_address_aget_printable: %s",
+ mu_strerror(rc)))
+ return WRDSE_NOSPACE;
+ return WRDSE_USERERR;
+ }
}
- return def->value;
+ return WRDSE_OK;
}
static void
-t_notify(struct mailevt *evt, int ev, wy_triplet_t trp)
+t_notify(struct mailevt *evt, int ev, wy_triplet_t *trp)
{
mu_address_t rcpt = NULL;
const char *errp;
char *text;
const char *msg;
- static struct wy_metadef email_meta[] = {
- { "email:admin", NULL, expand_email_admin, NULL },
- { "email:owner", NULL, expand_email_owner, NULL },
+ static struct wy_vardef email_def[] = {
+ { "email:admin", expand_email_admin },
+ { "email:owner", expand_email_owner },
{ NULL }
};
@@ -762,7 +776,7 @@ t_notify(struct mailevt *evt, int ev, wy_triplet_t trp)
wy_log(LOG_ERR, _("undefined message reference: %s"),
evt->msg);
else {
- text = wy_triplet_expand_param(msg, trp, email_meta);
+ text = wy_triplet_expand_param(msg, trp, email_def);
mail_send_message(rcpt, text, evt->sign_keys);
free(text);
}
@@ -807,7 +821,7 @@ mail_stats(struct mailevt *evt)
}
void
-wy_notify(void *data, int ev, wy_triplet_t trp)
+wy_notify(void *data, int ev, wy_triplet_t *trp)
{
struct mailevt *evt = data;
diff --git a/src/Makefile.am b/src/Makefile.am
index 0109754..397589a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -36,7 +36,6 @@ wydawca_SOURCES=\
interval.c\
job.c\
lock.c\
- meta.c\
module.c\
net.c\
pidfile.c\
diff --git a/src/dictionary.c b/src/dictionary.c
index 6a0ef18..7b915a4 100644
--- a/src/dictionary.c
+++ b/src/dictionary.c
@@ -191,7 +191,7 @@ dictionary_copy_result(struct dictionary *dict, const char *res, size_t size)
}
/* Quote non-printable characters in INPUT. Point *OUTPUT to the malloc'ed
- quoted string. Return its length. */
+ quoted string. Return 0 on success, 1 on error. */
int
dictionary_quote_string(struct dictionary *dict, void *handle,
const char *input, char **poutput, size_t * psize)
diff --git a/src/directive.c b/src/directive.c
index 8ce1ca2..c2ba03d 100644
--- a/src/directive.c
+++ b/src/directive.c
@@ -62,7 +62,7 @@ directive_parse(struct wy_triplet *trp)
/* If a directive KEY exists in the triplet TRP, return 0 and point PVAL
(unless it is NULL) to its value. Othervise, return 1. */
int
-directive_get_value(struct wy_triplet *trp, const char *key,
+directive_get_value(struct wy_triplet const *trp, const char *key,
const char **pval)
{
int keylen = strlen(key);
diff --git a/src/meta.c b/src/meta.c
deleted file mode 100644
index 734be50..0000000
--- a/src/meta.c
+++ b/dev/null
@@ -1,191 +0,0 @@
-/* wydawca - automatic release submission daemon
- Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2017, 2019
- 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"
-
-static const char *
-meta_expand(struct wy_metadef *def, void *data)
-{
- if (!def->value) {
- if (def->expand)
- return def->expand(def, data);
- def->value = "INTERNAL ERROR: NONEXPANDABLE DATA";
- }
- return def->value;
-}
-
-static const char *
-find_expansion_char(int c, struct wy_metadef *def, void *data)
-{
- for (; def->kw; def++)
- if (def->kw[1] == 0 && def->kw[0] == c)
- return meta_expand(def, data);
- return NULL;
-}
-
-static const char *
-find_expansion_word(const char *kw, size_t len, struct wy_metadef *def,
- void *data)
-{
- for (; def->kw; def++)
- if (strlen(def->kw) == len && memcmp(def->kw, kw, len) == 0)
- return meta_expand(def, data);
- return NULL;
-}
-
-char *
-meta_expand_string(const char *string, struct wy_metadef *def, void *data,
- struct dictionary *dict, void *handle)
-{
- const char *p, *s;
- char *res;
- struct grecs_txtacc *acc;
-
- if (!string)
- return NULL;
-
- acc = grecs_txtacc_create();
-
- for (p = string; *p;) {
- char *e;
- size_t len = strcspn(p, "$");
-
- grecs_txtacc_grow(acc, p, len);
- p += len;
- if (*p == '$') {
- switch (*++p) {
- case '$':
- grecs_txtacc_grow(acc, p, 1);
- p++;
- break;
-
- case '-':
- if (*++p)
- p++;
- break;
-
- case '{':
- e = strchr(p + 1, '}');
- if (e &&
- (s = find_expansion_word(p + 1, e - p - 1,
- def, data))) {
- if (dict) {
- char *newval;
- size_t len;
- /* FIXME: Return value? */
- dictionary_quote_string(dict,
- handle,
- s,
- &newval,
- &len);
- grecs_txtacc_grow(acc, newval,
- len);
- free(newval);
- } else
- grecs_txtacc_grow(acc, s,
- strlen(s));
- p = e + 1;
- } else {
- grecs_txtacc_grow(acc, p - 1, 2);
- p++;
- }
- break;
-
- default:
- if ((s = find_expansion_char(*p, def, data))
- != NULL)
- len = strlen(s);
- else {
- s = p - 1;
- len = 1;
- }
-
- if (dict) {
- char *newval;
- size_t len;
- /* FIXME: Return value? */
- dictionary_quote_string(dict,
- handle, s,
- &newval, &len);
- grecs_txtacc_grow(acc, newval, len);
- free(newval);
- } else
- grecs_txtacc_grow(acc, s, len);
- p++;
- }
- } else
- grecs_txtacc_grow(acc, p, 1);
- }
- grecs_txtacc_grow_char(acc, 0);
- res = grecs_txtacc_finish(acc, 1);
- grecs_txtacc_free(acc);
- return res;
-}
-
-void
-meta_free(struct wy_metadef *def)
-{
- for (; def->kw; def++) {
- if (def->storage) {
- free(def->storage);
- def->value = def->storage = NULL;
- }
- }
-}
-
-struct wy_metadef *
-metadef_join(struct wy_metadef *a, struct wy_metadef *b)
-{
- struct wy_metadef *np;
- size_t i, j;
-
- for (i = 0; a[i].kw; i++);
- if (b)
- for (j = 0; b[j].kw; j++);
- else
- j = 0;
- np = grecs_malloc((i + j + 1) * sizeof(a[0]));
- memcpy(np, a, i * sizeof(a[0]));
- if (j > 0)
- memcpy(np + i, b, j * sizeof(b[0]));
- np[i + j].kw = NULL;
- return np;
-}
-
-char *
-wy_expand_stats(const char *tmpl)
-{
- struct wy_metadef *exp;
- time_t t;
- size_t tc;
- char *text;
-
- tc = timer_get_count() * 3;
- exp = make_stat_expansion(tc + 1);
- time(&t);
- exp[0].kw = "date";
- exp[0].value = exp[0].storage = grecs_strdup(ctime(&t));
- exp[0].value[strlen(exp[0].value) - 1] = 0;
- timer_fill_meta(exp + 1, tc);
- text = meta_expand_string(tmpl, exp, NULL, NULL, NULL);
- meta_free(exp);
- timer_free_meta(exp + 1, tc);
- free(exp);
-
- return text;
-}
diff --git a/src/timer.c b/src/timer.c
index 866e993..39d9105 100644
--- a/src/timer.c
+++ b/src/timer.c
@@ -189,55 +189,3 @@ timer_get_count()
return _timer_count;
}
-struct timer_data {
- struct wy_metadef *def;
- size_t num;
-};
-
-int
-_fill_meta(void *sym, void *data)
-{
- struct timer_slot *slot = sym;
- struct timer_data *tp = data;
-#define CREATE_DEF(arg) \
- if (tp->num) { \
- char *buf = NULL; \
- size_t size = 0; \
- grecs_asprintf(&buf, &size, "timer:%s:%s", slot->name, #arg); \
- if (!buf) \
- grecs_alloc_die(); \
- tp->def->kw = buf; \
- tp->def->storage = \
- timer_format_time(wy_s_cat2(timer_get_,arg)(slot)); \
- tp->def->value = tp->def->storage; \
- tp->def->expand = NULL; \
- tp->def++; \
- tp->num--; \
- }
-
- CREATE_DEF(system);
- CREATE_DEF(real);
- CREATE_DEF(user);
-
- return tp->num <= 0;
-}
-
-void
-timer_fill_meta(struct wy_metadef *def, size_t num)
-{
- struct timer_data td;
- if (!timer_table)
- return;
- td.def = def;
- td.num = num;
- grecs_symtab_foreach(timer_table, _fill_meta, &td);
-}
-
-void
-timer_free_meta(struct wy_metadef *def, size_t num)
-{
- while (num--) {
- free(def->kw);
- def++;
- }
-}
diff --git a/src/triplet.c b/src/triplet.c
index 7c79af0..25271a3 100644
--- a/src/triplet.c
+++ b/src/triplet.c
@@ -493,47 +493,238 @@ triplet_remove_file(struct spool *spool, const char *name)
}
}
-static const char *
-expand_project_base(struct wy_metadef *def, void *data)
+/* FIXME */
+#define WY_EXP_DFL 0
+#define WY_EXP_TIMERS 0x1
+#define WY_EXP_STATS 0x2
+
+struct wy_varexp {
+ int flags;
+ struct wy_triplet *triplet;
+ struct wy_vardef **def;
+ char **timers;
+ struct dictionary *dict;
+ void *handle;
+};
+
+static int
+member(char **a, char const *s)
{
- struct wy_triplet *trp = data;
- return trp->project;
+ if (!a)
+ return 1;
+ while (*a) {
+ if (strcmp(*a, s) == 0)
+ return 1;
+ ++a;
+ }
+ return 0;
}
-static const char *
-expand_tag(struct wy_metadef *def, void *data)
+static void wy_ws_error(const char *fmt, ...);
+
+static int
+try_timer_var(char **retval, char const *var, size_t len, char **timers)
{
- struct wy_triplet *trp = data;
- return trp->spool->tag;
+ struct wordsplit ws;
+ int rc = WRDSE_UNDEF;
+
+ ws.ws_delim = ":";
+ ws.ws_error = wy_ws_error;
+ if (wordsplit_len(var, len, &ws,
+ WRDSF_DELIM
+ | WRDSF_NOVAR
+ | WRDSF_NOCMD
+ | WRDSF_ERROR
+ | WRDSF_SHOWERR)) {
+ wy_log(LOG_CRIT, _("failed to expand string %*.*s"),
+ (int)len, (int)len, var);
+ exit(EX_UNAVAILABLE);
+ }
+ if (ws.ws_wordc == 3 && strcmp(ws.ws_wordv[0], "timer") == 0) {
+ wydawca_timer_t t = NULL;
+
+ if (member(timers, ws.ws_wordv[1]))
+ t = timer_stop(ws.ws_wordv[1]);
+ if (t) {
+ double (*tfn)(wydawca_timer_t) = NULL;
+
+ if (strcmp(ws.ws_wordv[2], "real") == 0)
+ tfn = timer_get_real;
+ else if (strcmp(ws.ws_wordv[2], "user") == 0)
+ tfn = timer_get_user;
+ else if (strcmp(ws.ws_wordv[2], "system") == 0)
+ tfn = timer_get_system;
+
+ if (tfn) {
+ *retval = timer_format_time(tfn(t));
+ rc = WRDSE_OK;
+ }
+ }
+ }
+ wordsplit_free(&ws);
+ return rc;
}
-static const char *
-expand_url(struct wy_metadef *def, void *data)
+static int
+wy_varexp_lookup_triplet(char **ret, const char *var, size_t len,
+ struct wy_vardef **def,
+ struct wy_triplet *triplet)
{
- struct wy_triplet *trp = data;
- return trp->spool->url;
+ int i, j;
+
+ if (def) {
+ for (i = 0; def[i]; i++) {
+ for (j = 0; def[i][j].name; j++) {
+ if (strlen(def[i][j].name) == len
+ && memcmp(def[i][j].name, var, len) == 0) {
+ return def[i][j].expand(ret, triplet);
+ }
+ }
+ }
+ }
+ return WRDSE_UNDEF;
}
-static const char *
-expand_relative_dir(struct wy_metadef *def, void *data)
+static void
+trimnl(char *s)
{
- struct wy_triplet *trp = data;
- directive_get_value(trp, "directory", (const char **)&def->value);
- return def->value;
+ if (s) {
+ size_t len = strlen(s);
+ while (len > 0 && s[len-1] == '\n')
+ s[--len] = 0;
+ }
}
-static const char *
-expand_dest_dir(struct wy_metadef *def, void *data)
+static int
+wy_varexp_lookup(char **retval, const char *var, size_t len, void *clos)
{
- struct wy_triplet *trp = data;
- return trp->spool->dest_dir;
+ struct wy_varexp *exp = clos;
+ int rc;
+ char *res;
+
+ rc = wy_varexp_lookup_triplet(&res, var, len, exp->def, exp->triplet);
+ if (rc != WRDSE_OK && (exp->flags & WY_EXP_TIMERS))
+ rc = try_timer_var(&res, var, len, exp->timers);
+ if (rc != WRDSE_OK && (exp->flags & WY_EXP_STATS))
+ rc = wy_stat_expansion(&res, var, len);
+ if (rc == WRDSE_OK) {
+ trimnl(res);
+ if (exp->dict) {
+ /* FIXME: Revise return code */
+ dictionary_quote_string(exp->dict,
+ exp->handle,
+ res,
+ retval,
+ NULL);
+ } else
+ *retval = res;
+ }
+ return rc;
+}
+
+static void
+wy_ws_error(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ wy_vlog(LOG_ERR, fmt, ap);
+ va_end(ap);
}
-static const char *
-expand_source_dir(struct wy_metadef *def, void *data)
+char *
+wy_expand_string(char const *str, struct wy_varexp *varexp)
{
- struct wy_triplet *trp = data;
- return trp->spool->source_dir;
+ struct wordsplit ws;
+ char *retval;
+ char *lenv[3];
+ time_t t;
+
+ lenv[0] = "date";
+ time(&t);
+ lenv[1] = strdup(ctime(&t));
+ lenv[2] = NULL;
+
+ ws.ws_namechar = ":";
+ ws.ws_options = WRDSO_NAMECHAR;
+ ws.ws_closure = varexp;
+ ws.ws_getvar = wy_varexp_lookup;
+ ws.ws_error = wy_ws_error;
+ ws.ws_env = (const char **)lenv;
+
+ if (wordsplit(str, &ws,
+ WRDSF_OPTIONS
+ | WRDSF_ENV
+ | WRDSF_ENV_KV
+ | WRDSF_GETVAR
+ | WRDSF_CLOSURE
+ | WRDSF_NOCMD
+ | WRDSF_UNDEF
+ | WRDSF_NOSPLIT
+ | WRDSF_ERROR
+ | WRDSF_SHOWERR)) {
+ wy_log(LOG_CRIT, _("failed to expand string %s"), str);
+ exit(EX_UNAVAILABLE);
+ }
+
+ retval = ws.ws_wordv[0];
+ ws.ws_wordv[0] = NULL;
+ wordsplit_free(&ws);
+
+ return retval;
+}
+
+int
+wy_expand_copy(char **ret, char const *s)
+{
+ if (s) {
+ char *copy = strdup(s);
+ if (!copy)
+ return WRDSE_NOSPACE;
+ *ret = copy;
+ return WRDSE_OK;
+ }
+ return WRDSE_UNDEF;
+}
+
+#define DECL_TRIPLET_EXP_NAME(name) \
+wy_s_cat2(expand_,name)
+
+#define DECL_TRIPLET_EXP(name, member) \
+static int \
+DECL_TRIPLET_EXP_NAME(name)(char **ret, struct wy_triplet *trp) \
+{ \
+ if (trp) \
+ return wy_expand_copy(ret, trp->member); \
+ return WRDSE_UNDEF; \
+}
+
+DECL_TRIPLET_EXP(user, uploader->name)
+DECL_TRIPLET_EXP(project, project)
+DECL_TRIPLET_EXP(url, spool->url)
+DECL_TRIPLET_EXP(spool, spool->tag)
+DECL_TRIPLET_EXP(dest_dir, spool->dest_dir)
+DECL_TRIPLET_EXP(source_dir, spool->source_dir)
+
+static int
+expand_relative_dir(char **ret, struct wy_triplet *trp)
+{
+ if (trp) {
+ char const *dir;
+ if (directive_get_value(trp, "directory", &dir) == 0)
+ return wy_expand_copy(ret, dir);
+ }
+ return WRDSE_UNDEF;
+}
+
+static int
+expand_comment(char **ret, struct wy_triplet *trp)
+{
+ if (trp) {
+ char const *dir;
+ if (directive_get_value(trp, "comment", &dir) == 0)
+ return wy_expand_copy(ret, dir);
+ }
+ return WRDSE_UNDEF;
}
static void
@@ -565,7 +756,7 @@ static int
format_file_data(struct wy_triplet *trp, enum file_type type, char **pret)
{
char modes[11];
- struct file_info *info = trp->file + type;
+ struct file_info const *info = trp->file + type;
char timebuf[sizeof "YYYY-MM-DD HH:MM:SS +0000"];
struct passwd *pw;
struct group *grp;
@@ -603,8 +794,8 @@ format_file_data(struct wy_triplet *trp, enum file_type type, char **pret)
group_name = grp->gr_name;
/* Size */
- if (grecs_asprintf
- (&sptr, &slen, "%lu", (unsigned long)info->sb.st_size))
+ if (grecs_asprintf(&sptr, &slen, "%lu",
+ (unsigned long)info->sb.st_size))
grecs_alloc_die();
/* Figure out padding and format the buffer */
@@ -623,13 +814,16 @@ format_file_data(struct wy_triplet *trp, enum file_type type, char **pret)
return 0;
}
-static const char *
-expand_triplet_ls_full(struct wy_metadef *def, void *data)
+static int
+expand_triplet_ls_full(char **ret, struct wy_triplet *trp)
{
- struct wy_triplet *trp = data;
char *buf[FILE_TYPE_COUNT] = { NULL, NULL, NULL };
size_t size = 0;
+ char *value;
+ if (!trp)
+ return WRDSE_UNDEF;
+
if (format_file_data(trp, file_dist, &buf[file_dist]) == 0)
size += strlen(buf[file_dist]) + 1;
if (format_file_data(trp, file_signature, &buf[file_signature]) == 0)
@@ -637,282 +831,219 @@ expand_triplet_ls_full(struct wy_metadef *def, void *data)
if (format_file_data(trp, file_directive, &buf[file_directive]) == 0)
size += strlen(buf[file_directive]) + 1;
- def->value = def->storage = grecs_malloc(size + 1);
- def->value[0] = 0;
+ value = malloc(size + 1);
+ if (!value)
+ return WRDSE_NOSPACE;
+ value[0] = 0;
if (buf[file_dist]) {
- strcat(def->value, buf[file_dist]);
- strcat(def->value, "\n");
+ strcat(value, buf[file_dist]);
+ strcat(value, "\n");
}
if (buf[file_signature]) {
- strcat(def->value, buf[file_signature]);
- strcat(def->value, "\n");
+ strcat(value, buf[file_signature]);
+ strcat(value, "\n");
}
if (buf[file_directive]) {
- strcat(def->value, buf[file_directive]);
- strcat(def->value, "\n");
+ strcat(value, buf[file_directive]);
+ strcat(value, "\n");
}
free(buf[file_dist]);
free(buf[file_signature]);
free(buf[file_directive]);
- return def->value;
+
+ *ret = value;
+ return WRDSE_OK;
}
-static const char *
-expand_triplet_ls_upload(struct wy_metadef *def, void *data)
+static int
+expand_triplet_ls_upload(char **ret, struct wy_triplet *trp)
{
- struct wy_triplet *trp = data;
char *buf[2] = { NULL, NULL };
size_t size = 0;
+ char *value;
+
+ if (!trp)
+ return WRDSE_UNDEF;
if (format_file_data(trp, file_dist, &buf[file_dist]) == 0)
size += strlen(buf[file_dist]) + 1;
if (format_file_data(trp, file_signature, &buf[file_signature]) == 0)
size += strlen(buf[file_signature]) + 1;
- def->value = def->storage = grecs_malloc(size + 1);
- def->value[0] = 0;
+ value = malloc(size + 1);
+ value[0] = 0;
if (buf[file_dist]) {
- strcat(def->value, buf[file_dist]);
- strcat(def->value, "\n");
+ strcat(value, buf[file_dist]);
+ strcat(value, "\n");
}
if (buf[file_signature]) {
- strcat(def->value, buf[file_signature]);
- strcat(def->value, "\n");
+ strcat(value, buf[file_signature]);
+ strcat(value, "\n");
}
free(buf[file_dist]);
free(buf[file_signature]);
- return def->value;
-}
-
-static const char *
-expand_triplet_dist(struct wy_metadef *def, void *data)
-{
- struct wy_triplet *trp = data;
- return trp->file[file_dist].name;
-}
-
-static const char *
-expand_triplet_sig(struct wy_metadef *def, void *data)
-{
- struct wy_triplet *trp = data;
- return trp->file[file_signature].name;
-}
+ *ret = value;
-static const char *
-expand_triplet_dir(struct wy_metadef *def, void *data)
-{
- struct wy_triplet *trp = data;
- return trp->file[file_directive].name;
+ return WRDSE_OK;
}
-static const char *
-expand_triplet_ls_dist(struct wy_metadef *def, void *data)
-{
- struct wy_triplet *trp = data;
- format_file_data(trp, file_dist, &def->storage);
- def->value = def->storage;
- return def->value;
-}
+DECL_TRIPLET_EXP(triplet_dist, file[file_dist].name)
+DECL_TRIPLET_EXP(triplet_sig, file[file_signature].name)
+DECL_TRIPLET_EXP(triplet_dir, file[file_directive].name)
-static const char *
-expand_triplet_ls_sig(struct wy_metadef *def, void *data)
-{
- struct wy_triplet *trp = data;
- format_file_data(trp, file_signature, &def->storage);
- def->value = def->storage;
- return def->value;
-}
-
-static const char *
-expand_triplet_ls_directive(struct wy_metadef *def, void *data)
+static int
+expand_triplet_ls_dist(char **ret, struct wy_triplet *trp)
{
- struct wy_triplet *trp = data;
- format_file_data(trp, file_directive, &def->storage);
- def->value = def->storage;
- return def->value;
+ if (!trp)
+ return WRDSE_UNDEF;
+ return format_file_data(trp, file_dist, ret);
}
-static const char *
-expand_user_name(struct wy_metadef *def, void *data)
+static int
+expand_triplet_ls_sig(char **ret, struct wy_triplet *trp)
{
- struct wy_triplet *trp = data;
- if (trp->uploader)
- return trp->uploader->name;
- def->value = "UNKNOWN";
- return def->value;
+ if (!trp)
+ return WRDSE_UNDEF;
+ return format_file_data(trp, file_signature, ret);
}
-static const char *
-expand_user_real_name(struct wy_metadef *def, void *data)
+static int
+expand_triplet_ls_dir(char **ret, struct wy_triplet *trp)
{
- struct wy_triplet *trp = data;
- if (trp->uploader)
- return trp->uploader->realname;
- def->value = "UNKNOWN";
- return def->value;
+ if (!trp)
+ return WRDSE_UNDEF;
+ return format_file_data(trp, file_directive, ret);
}
-static const char *
-expand_user_email(struct wy_metadef *def, void *data)
-{
- struct wy_triplet *trp = data;
- if (trp->uploader)
- return trp->uploader->email;
- def->value = "UNKNOWN";
- return def->value;
-}
+DECL_TRIPLET_EXP(real_name, uploader->realname)
+DECL_TRIPLET_EXP(expand_user_email, uploader->email)
-static const char *
-expand_email_user(struct wy_metadef *def, void *data)
+static int
+expand_email_user(char **ret, struct wy_triplet *trp)
{
- struct wy_triplet *trp = data;
- if (trp->uploader) {
+ if (trp && trp->uploader) {
size_t size = 0;
- if (grecs_asprintf(&def->storage, &size, "\"%s\" <%s>",
+ *ret = NULL;
+ if (grecs_asprintf(ret, &size, "\"%s\" <%s>",
trp->uploader->realname,
trp->uploader->email))
- grecs_alloc_die();
- def->value = def->storage;
+ return WRDSE_NOSPACE;
+ return WRDSE_OK;
}
- return def->value;
-}
-
-static const char *
-expand_report(struct wy_metadef *def, void *data)
-{
- return report_string;
+ return WRDSE_UNDEF;
}
-static const char *
-expand_comment(struct wy_metadef *def, void *data)
+//FIXME: static env?
+static int
+expand_report(char **ret, struct wy_triplet *trp)
{
- struct wy_triplet *trp = data;
- if (directive_get_value(trp, "comment", (const char **)&def->value))
- def->value = "";
- return def->value;
+ return wy_expand_copy(ret, report_string);
}
-static const char *
-expand_check_diagn(struct wy_metadef *def, void *data)
-{
- struct wy_triplet *trp = data;
- return trp->check_diag;
-}
+DECL_TRIPLET_EXP(check_diagn, check_diag);
-static const char *
-expand_check_result(struct wy_metadef *def, void *data)
+static int
+expand_check_result(char **ret, struct wy_triplet *trp)
{
- struct wy_triplet *trp = data;
- int status = trp->check_result;
+ int status;
+ size_t size = 0;
- if (status == 0)
- return def->value = "0";
- else if (WIFEXITED(status)) {
- size_t size = 0;
- def->storage = NULL;
- if (grecs_asprintf(&def->storage, &size,
- "%d", WEXITSTATUS(status)))
- grecs_alloc_die();
+ if (!trp)
+ return WRDSE_UNDEF;
+
+ status = trp->check_result;
+
+ *ret = NULL;
+ if (status == 0) {
+ *ret = strdup("0");
+ if (!*ret)
+ return WRDSE_NOSPACE;
+ } else if (WIFEXITED(status)) {
+ if (grecs_asprintf(ret, &size, "%d", WEXITSTATUS(status)))
+ return WRDSE_NOSPACE;
} else if (WIFSIGNALED(status)) {
- size_t size = 0;
- def->storage = NULL;
- if (grecs_asprintf(&def->storage, &size, "SIG+%d",
- WTERMSIG(status)))
- grecs_alloc_die();
- } else
- return def->value = "[unrecognized return code]";
- return def->value = def->storage;
-}
-
-#define DECL_EXPAND_TIMER(what) \
-static const char * \
-wy_s_cat2(expand_timer_,what) (struct wy_metadef *def, void *data) \
-{ \
- wydawca_timer_t t = timer_stop ((char*)def->data); \
- def->storage = timer_format_time (wy_s_cat2(timer_get_,what) (t)); \
- return def->value = def->storage; \
+ if (grecs_asprintf(ret, &size, "SIG+%d", WTERMSIG(status)))
+ return WRDSE_NOSPACE;
+ } else if (grecs_asprintf(ret, &size, "[unrecognized return code %d]",
+ status))
+ return WRDSE_NOSPACE;
+ return WRDSE_OK;
}
-
-DECL_EXPAND_TIMER(real)
-DECL_EXPAND_TIMER(user)
-DECL_EXPAND_TIMER(system)
-#define DECL_TIMER(name,t) \
- { "timer:" #name ":" #t, NULL, wy_s_cat2(expand_timer_,t), NULL, #name }
-#define DECL_FULL_TIMER(name) \
- DECL_TIMER(name, real), \
- DECL_TIMER(name, user), \
- DECL_TIMER(name, system)
-struct wy_metadef triplet_default_meta[] = {
- { "u", NULL, expand_user_name, NULL },
- { "user", NULL, expand_user_name, NULL },
- { "user:name", NULL, expand_user_name, NULL },
- { "p", NULL, expand_project_base, NULL },
- { "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 },
- { "comment", NULL, expand_comment, NULL },
+
+struct wy_vardef triplet_query_def[] = {
+ { "user", DECL_TRIPLET_EXP_NAME(user) },
+ { "user:name", DECL_TRIPLET_EXP_NAME(user) },
+ { "project", DECL_TRIPLET_EXP_NAME(project) },
+ { "url", DECL_TRIPLET_EXP_NAME(url) },
+ { "spool", DECL_TRIPLET_EXP_NAME(spool) },
+ { "dir", expand_relative_dir },
+ { "dest_dir", DECL_TRIPLET_EXP_NAME(dest_dir) },
+ { "source_dir", DECL_TRIPLET_EXP_NAME(source_dir) },
+ { "comment", DECL_TRIPLET_EXP_NAME(comment) },
{ NULL }
};
-
+
char *
triplet_expand_dictionary_query(struct dictionary *dict, void *handle,
- struct wy_triplet const *trp)
+ struct wy_triplet *trp)
{
- char *p = meta_expand_string(dict->query, triplet_default_meta,
- (void*) trp,
- dict, handle);
- meta_free(triplet_default_meta);
- return p;
+ struct wy_vardef *vd[2] = { triplet_query_def, NULL };
+ struct wy_varexp varexp = {
+ .flags = WY_EXP_DFL,
+ .triplet = trp,
+ .dict = dict,
+ .handle = handle,
+ .def = vd
+ };
+ return wy_expand_string(dict->query, &varexp);
}
-struct wy_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 },
- { "triplet:dist", NULL, expand_triplet_dist, NULL },
- { "triplet:sig", NULL, expand_triplet_sig, NULL },
- { "triplet:dir", NULL, expand_triplet_dir, NULL },
- { "triplet:ls:full", NULL, expand_triplet_ls_full, NULL },
- { "triplet:ls:upload", NULL, expand_triplet_ls_upload, NULL },
- { "triplet:ls:dist", NULL, expand_triplet_ls_dist, NULL },
- { "triplet:ls:sig", NULL, expand_triplet_ls_sig, NULL },
- { "triplet:ls:dir", NULL, expand_triplet_ls_directive, NULL },
- { "check:result", NULL, expand_check_result, NULL },
- { "check:diagn", NULL, expand_check_diagn, NULL },
- { "user", NULL, expand_user_name, NULL },
- { "user:name", NULL, expand_user_name, NULL },
- { "user:real-name", NULL, expand_user_real_name, NULL },
- { "user:email", NULL, expand_user_email, NULL },
- { "email:user", NULL, expand_email_user, NULL },
- { "report", NULL, expand_report, NULL },
- { "comment", NULL, expand_comment, NULL },
- DECL_FULL_TIMER(wydawca),
- DECL_FULL_TIMER(triplet),
- DECL_FULL_TIMER(spool),
+struct wy_vardef triplet_def[] = {
+ { "triplet:dist", DECL_TRIPLET_EXP_NAME(triplet_dist) },
+ { "triplet:sig", DECL_TRIPLET_EXP_NAME(triplet_sig) },
+ { "triplet:dir", DECL_TRIPLET_EXP_NAME(triplet_dir) },
+ { "triplet:ls:full", expand_triplet_ls_full },
+ { "triplet:ls:upload", expand_triplet_ls_upload },
+ { "triplet:ls:dist", expand_triplet_ls_dist },
+ { "triplet:ls:sig", expand_triplet_ls_sig },
+ { "triplet:ls:dir", expand_triplet_ls_dir },
+ { "check:result", expand_check_result },
+ { "check:diagn", DECL_TRIPLET_EXP_NAME(check_diagn) },
+
+ { "user:real_name", DECL_TRIPLET_EXP_NAME(real_name) },
+
+ { "user:email", DECL_TRIPLET_EXP_NAME(expand_user_email) },
+ { "email:user", expand_email_user },
+ { "report", expand_report },
{ NULL}
};
char *
-wy_triplet_expand_param(const char *tmpl, struct wy_triplet const *trp,
- struct wy_metadef *xmeta)
+wy_triplet_expand_param(const char *tmpl, struct wy_triplet *trp,
+ struct wy_vardef *extra)
{
- char *p;
- struct wy_metadef *mp = metadef_join(triplet_meta, xmeta);
-
- p = meta_expand_string(tmpl, mp, (void *)trp, NULL, NULL);
- meta_free(mp);
- free(mp);
- return p;
+ struct wy_vardef *vd[] = { triplet_query_def, triplet_def, extra, NULL };
+ static char *timers[] = { "wydawca", "triplet", "spool", NULL };
+ struct wy_varexp varexp = {
+ .flags = WY_EXP_TIMERS,
+ .triplet = trp,
+ .def = vd,
+ .timers = timers
+ };
+ return wy_expand_string(tmpl, &varexp);
}
+char *
+wy_expand_stats(const char *tmpl)
+{
+ struct wy_varexp varexp = {
+ .flags = WY_EXP_TIMERS|WY_EXP_STATS,
+ };
+ return wy_expand_string(tmpl, &varexp);
+}
+
struct wy_user *
wy_triplet_get_uploaders(struct wy_triplet *trp)
{
diff --git a/src/wydawca.c b/src/wydawca.c
index 00d779c..9ec0cc7 100644
--- a/src/wydawca.c
+++ b/src/wydawca.c
@@ -108,10 +108,8 @@ static void (*log_printer) (int prio, const char *fmt, va_list ap) =
stderr_printer;
void
-wy_log(int prio, char *fmt, ...)
+wy_vlog(int prio, char const *fmt, va_list ap)
{
- va_list ap;
-
switch (prio) {
case LOG_EMERG:
case LOG_ALERT:
@@ -124,13 +122,20 @@ wy_log(int prio, char *fmt, ...)
UPDATE_STATS(WY_STAT_WARNINGS);
}
- va_start(ap, fmt);
log_printer(prio, fmt, ap);
+}
+
+void
+wy_log(int prio, char const *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ wy_vlog(prio, fmt, ap);
va_end(ap);
}
void
-wy_dbg(char *fmt, ...)
+wy_dbg(char const *fmt, ...)
{
va_list ap;
@@ -171,7 +176,7 @@ static char *stat_kwname[WY_MAX_STAT] = {
"stat:archives",
"stat:symlinks",
"stat:rmsymlinks",
- "stat:check-failures"
+ "stat:check_failures"
};
int
@@ -185,34 +190,21 @@ wy_stat_mask_p(unsigned long mask)
return 0;
}
-static const char *
-stat_expand(struct wy_metadef *def, void *data)
-{
- size_t size = 0;
- def->storage = NULL;
- if (grecs_asprintf(&def->storage, &size, "%u",
- wydawca_stat[(int)def->data]))
- grecs_alloc_die();
- def->value = def->storage;
- return def->value;
-}
-
-struct wy_metadef *
-make_stat_expansion(size_t count)
+int
+wy_stat_expansion(char **ret, char const *name, size_t len)
{
int i;
- struct wy_metadef *def, *p;
- def = grecs_calloc(WY_MAX_STAT + count + 1, sizeof(def[0]));
- p = def + count;
- for (i = 0; i < WY_MAX_STAT; i++, p++) {
- p->kw = stat_kwname[i];
- p->value = NULL;
- p->storage = NULL;
- p->expand = stat_expand;
- p->data = (void *)i;
+
+ for (i = 0; i < WY_MAX_STAT; i++) {
+ if (strlen(stat_kwname[i]) == len
+ && memcmp(stat_kwname[i], name, len) == 0) {
+ size_t size = 0;
+ *ret = NULL;
+ if (grecs_asprintf(ret, &size, "%u", wydawca_stat[i]))
+ return WRDSE_NOSPACE;
+ }
}
- p->kw = NULL;
- return def;
+ return WRDSE_OK;
}
void
diff --git a/src/wydawca.h b/src/wydawca.h
index 580d0be..63da9bb 100644
--- a/src/wydawca.h
+++ b/src/wydawca.h
@@ -277,12 +277,6 @@ void notify_stats(void);
void notify_flush(struct spool *sp);
-char *meta_expand_string(const char *string, struct wy_metadef *def, void *data,
- struct dictionary *dict, void *handle);
-void meta_free(struct wy_metadef *def);
-struct wy_metadef *metadef_join(struct wy_metadef *a, struct wy_metadef *b);
-
-
/* Modules */
struct module {
@@ -365,7 +359,6 @@ extern struct notification *default_notification;
} while (0)
int stat_mask_p(unsigned long mask);
-struct wy_metadef *make_stat_expansion(size_t count);
void initstats(void);
void logstats(void);
@@ -412,7 +405,7 @@ struct wy_triplet *link_processable_triplets(void);
size_t count_collected_triplets(void);
char *triplet_expand_dictionary_query(struct dictionary *dict, void *handle,
- struct wy_triplet const *trp);
+ struct wy_triplet *trp);
void triplet_remove_file(struct spool *spool, const char *name);
@@ -447,7 +440,7 @@ struct wy_user *uploader_find_frp(struct wy_user *list,
/* Directive file support */
int directive_parse(struct wy_triplet *trp);
-int directive_get_value(struct wy_triplet *trp, const char *key,
+int directive_get_value(struct wy_triplet const *trp, const char *key,
const char **pval);
int directive_pack_version(const char *val, unsigned *pversion);
int directive_unpack_version(unsigned version, char **pbuf, size_t * psize);
@@ -521,8 +514,6 @@ double timer_get_user(wydawca_timer_t t);
double timer_get_system(wydawca_timer_t t);
char *timer_format_time(double t);
size_t timer_get_count(void);
-void timer_fill_meta(struct wy_metadef *def, size_t num);
-void timer_free_meta(struct wy_metadef *def, size_t num);
void report_init(void);
void report_add(const char *fmt, ...);
@@ -572,3 +563,5 @@ int watcher_run(int);
# define watcher_init() -1
# define watcher_run(c)
#endif
+
+int wy_stat_expansion(char **ret, char const *name, size_t len);
diff --git a/tests/etc/notify.rcin b/tests/etc/notify.rcin
index 67b7096..ea2d2bb 100644
--- a/tests/etc/notify.rcin
+++ b/tests/etc/notify.rcin
@@ -35,7 +35,7 @@ Subject: Upload of ${project} successful
Upload of ${project} to ${url}/${dir} finished successfully.
Files uploaded:
-${triplet:ls:upload}$-
+${triplet:ls:upload}
Regards,
Wydawca
@@ -53,10 +53,10 @@ notify-event {
message <<EOT
Subject: Upload of ${project} successful
-${user:real-name} (${user:email}) successfully uploaded files
+${user:real_name} (${user:email}) successfully uploaded files
for ${project} to ${url}/${dir}. Files uploaded:
-${triplet:ls:upload}$-
+${triplet:ls:upload}
Regards,
Wydawca
@@ -78,10 +78,10 @@ Subject: Suspicious upload of ${project}
Someone not authorized to make releases for ${project}
has attempted to upload the following files to ${url}/${dir}:
-${triplet:ls:full}$-
+${triplet:ls:full}
This upload has been ignored and the files removed. The person who attempted
-the upload was ${user:real-name}, user name ${user:name}, email ${user:email}.
+the upload was ${user:real_name}, user name ${user:name}, email ${user:email}.
If you think this is an error and wish this user to be authorized to make
releases for ${project}, please contact <puszcza-hackers@gnu.org.ua>.
Otherwise, let us know so we could undertake appropriate measures.
@@ -134,7 +134,7 @@ notify-event {
message <<EOT
Subject: Suspicious upload of ${project}
-${user:real-name} (${user:email}) has tried to make a release
+${user:real_name} (${user:email}) has tried to make a release
for ${project}. However, the signature of the directive file was wrong,
which looks suspicious. The person uploaded the following files:
@@ -190,7 +190,7 @@ notify-event {
message <<EOT
Subject: Suspicious upload of ${project}
-${user:real-name} (${user:email}) has tried to make a release
+${user:real_name} (${user:email}) has tried to make a release
for ${project}. However, the detached signature file was wrong,
which looks suspicious. The person uploaded the following files:
@@ -216,7 +216,7 @@ Subject: ${triplet:dist} rejected
Your upload of ${triplet:dist} has been rejected by the distribution
verification procedure with the following diagnostics:
-${check:diagn}$-
+${check:diagn}
Please fix the tarball and resubmit.

Return to:

Send suggestions and report system problems to the System administrator.