root/bin/pl-conf

Revision 323:2fb49308319a, 12.4 KB (checked in by Anselm Lingnau <anselm@…>, 9 months ago)

Configuration parameter system reworked.
This adds a list of ?official? configuration parameters together with their
types, default values, and explanatory messages. An extended method,
DB::get_config_x(), is used to retrieve all of this info, and DB::get_config()
is changed to return the default value from the list if the parameter is not
set in the database.

In the pl-conf command, there are some new --query suboptions: --all outputs
all configuration parameters, not just those that are in the current list
database; --modified outputs only those parameters whose values differ from
the built-in defaults; and --defaults outputs the built-in default values
of parameters rather than their actual values.

This change is really for the benefit of Project Guinevere, which needs to
be able to produce a list configuration page containing all possible parameters
rather than just the ones that happen to be in the database at that point.
We will still have to go through the files and adapt all the calls to
get_config() to remove the hard-coded defaults, and we can also get rid of the
big default parameter list in DB.pm.

  • Property exe set to *
Line 
1#!/usr/bin/perl
2
3=head1 NAME
4
5pl-conf - Query or modify Project Lancelot list configuration parameters
6
7=head1 SYNOPSIS
8
9  pl-conf [--query|-q] [--all|-A] [--modified|-M] [--defaults|-D]
10            [--valueonly|-h] list@domain [parameter ...]
11  pl-conf [--set|-s] list@domain ["parameter = value" ...]
12  pl-conf [--import|-i] [--onlynew|-n] list@domain [file ...]
13  pl-conf [--delete|-d] list@domain [parameter ...]
14  pl-conf [--merge|-m] --into=list@domain list@domain
15  pl-conf [--unmerge|-u] list@domain
16  pl-conf [--alias|-a] list@domain [alias]
17
18=head1 OVERVIEW
19
20The B<pl-conf> command allows a list owner to query, change, or
21delete various configuration parameters of a Lancelot list.
22
23=head1 DESCRIPTION
24
25The B<pl-conf> command can be used for four different purposes:
26
27=head2 QUERYING PARAMETERS
28
29With the B<--query> (or B<-q>) option, B<pl-conf> will print either
30all of the configuration parameters in the database (if no parameter
31names are given) or the specified parameters to standard output, like
32
33  list.address = test@example.com
34  list.owneraddress = alfred@example.com
35  ...
36
37If there is a single argument which ends in .*, all configuration
38parameters whose names start with the part preceding the * will be
39considered.
40
41The parameter name and equals sign can be suppressed using the
42B<--valueonly> option but only for parameters listed on the command
43line.  This is convenient if the parameter value is to be used, e.g.,
44in a shell script.
45
46With the B<--modified> (or B<-M>) option, B<--query> only lists those
47parameters whose values differ from their built-in defaults. With the
48B<--defaults> (or B<-D>) option, the built-in default values of
49parameters are displayed instead of their actual values. With the
50B<--all> (or B<-A>) option, all parameters known to Project Lancelot
51are displayed, not just those that actually occur in the database of
52the list being considered.
53
54The output of B<pl-conf --query> is suitable as input for
55B<pl-conf --import>, which is useful to clone, rename, or migrate Lancelot
56lists.
57
58=head2 SETTING PARAMETERS
59
60With the B<--set> (or B<-s>) option, B<pl-conf> will take
61configuration parameter assignments from the command line and enter
62them into the configuration database. A parameter's new value consists
63of everything to the right of the equals sign excluding leading or
64trailing spaces; to set a value that begins or ends with whitespace
65use quotes as in
66
67  pl-conf --set 'mail.subjecttag = "[Test] "'
68
69(Only double quotes are allowed; to include a double quote in a
70double-quoted string, put a backslash in front of it.)
71
72=head2 IMPORTING PARAMETERS WHOLESALE
73
74With the B<--import> (or B<-i>) option, B<pl-conf> reads configuration
75parameter assignments from files mentioned on the command line, or from
76standard input. Blank lines and lines starting with the comment symbol,
77"#", are ignored.
78
79If the B<--onlynew> (or B<-n>) option is given, only those configuration
80parameters from the input are taken into account that do not already
81exist in the configuration database. This is handy if Lancelot acquires
82new features with corresponding configuration parameters.
83
84=head2 DELETING PARAMETERS
85
86With the B<--delete> (or B<-d>) option, B<pl-conf> deletes the configuration
87parameters listed on the command line from the database.
88
89=head2 MERGING AND UNMERGING DATABASES
90
91It is possible to combine the databases of several lists into one database
92file, which allows them to be managed together using a web frontend such
93as Project Guinevere. To do this, decide which of the databases is to be
94the "master" database, and merge the other database(s) into it using the
95B<--merge> option of B<pl-conf>, as in
96
97  pl-conf --merge --into=master@example.com test@example.com
98
99After this, all Project Lancelot commands can be used on
100B<test@example.com> as before, except changes will now be made to the
101appropriate parts of the B<master@example.com> database.
102
103Unmerging databases using the B<--unmerge> option isn't implemented yet.
104
105=head2 LIST ALIASES
106
107Aliases for mailing list addresses can be introduced using the B<--alias>
108(or B<-a>) option. These are strictly for convenience when using the
109Project Lancelot command-line tools and have no bearing on mail delivery.
110
111The command
112
113  pl-conf --alias test@example.com test
114
115introduces B<test> as an alias for the B<test@example.com> list. This
116means that you may now use commands like
117
118  pl-conf -q test
119
120in addition to
121
122  pl-conf -q test@example.com
123
124A single list may have arbitrarily many aliases.
125
126Invoking B<pl-conf --alias> with just the list address will display that
127list's alias(es), if any. To find the list that an alias points to, use
128a command like
129
130  pl-conf -qh test list.address
131
132Aliases are implemented by means of symbolic links in the F<$HOME/.pl>
133directory. You can remove an alias by removing the corresponding symbolic
134link from that directory.
135
136Project Lancelot maintains an implicit alias, B<.>, to the mailing list
137most recently used in a Project Lancelot command (except B<pl-incoming>).
138This means that in
139
140  pl-list -a test@example.com "hugo*"
141  pl-subscribe . hugo@example.com
142
143the second command will apply to the B<test@example.com> list.
144
145=head1 OPTIONS
146
147=over 4
148
149=item B<--alias>, B<-a>
150
151Introduces a command-line alias for a mailing list.
152
153=item B<--all>, B<-A>
154
155With B<--query>, outputs all configuration parameters known to Project
156Lancelot, not just those that actually occur in the database of the
157current list.
158
159=item B<--defaults>, B<-D>
160
161With B<--query>, causes the program to output the built-in default values
162of parameters rather than their actual values.
163
164=item B<--delete>, B<-d>
165
166Causes the program to delete the configuration parameters mentioned on
167the command line from a list's database.
168
169=item B<--help>, B<-?>
170
171Causes the program to output a brief usage explanation and exit.
172
173=item B<--import>, B<-i>
174
175Causes the program to read configuration parameter assignments from
176files mentioned on the command line, or standard input, and add them
177to a list's database. Blank lines and comment lines are ignored.
178
179=item B<--into>
180
181When merging a list's database into another using the B<--merge> option,
182this specifies the list that the given list's database should be merged
183into.
184
185=item B<--modified>, B<-M>
186
187With B<--query>, outputs only those parameter whose values differ from
188their built-in default values.
189
190=item B<--onlynew>, B<-n>
191
192When importing configuration parameters wholesale using B<--import>,
193causes the program to ignore configuration parameters that already
194exist in the database.
195
196=item B<--query>, B<-q>
197
198Causes the program to output the values of some or all of a list's
199configuration parameters.
200
201=item B<--set>, B<-s>
202
203Causes the program to take configuration parameter assignments from
204the command line and add them to a list's database.
205
206=item B<--user>, B<-u>
207
208Pretends to be the given user for the purposes of locating the list's
209database. The database's file permissions must still allow access so this
210probably works best if you are running as root or have group write
211permission to the database.
212
213=item B<--valueonly>, B<-h>
214
215When used together with B<--query>, omits the parameter name and equals
216sign from the output for explicitly named parameters.
217
218When used together with B<--set> or B<--import>, this option is ignored.
219
220=item B<--verbose>, B<-v>
221
222Causes the program to output messages about its progress to the
223standard error channel.
224
225=back
226
227=head1 SEE ALSO
228
229pl-init(1),  pl-list(1), pl-subchange(1), pl-subscribe(1), pl-unsubscribe(1)
230
231=head1 BUGS
232
233There is no fixed set of valid configuration parameters; whatever is
234passed to the command will be entered in the database.
235
236=head1 AUTHOR
237
238Anselm Lingnau <anselm@anselms.net>
239
240=head1 COPYRIGHT AND LICENSE
241
242Copyright 2004 by Anselm Lingnau. This program is free software; you
243may redistribute it and/or modify it under the terms of the GNU
244General Public License as published by the Free Software Foundation;
245either version 2 of the License, or (at your option) any later version.
246
247This program is distributed in the hope that it will be useful, but
248WITHOUT ANY WARRANTY; without even the implied warranty of
249MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
250General Public License for more details.
251
252You should have received a copy of the GNU General Public License
253along with this program; if not, refer to
254<URL:http://www.gnu.org/copyleft/gpl.html>. You may also obtain it by
255writing to the Free Software Foundation, Inc., 59 Temple Place - Suite
256330, Boston, MA 02111-1307, USA.
257
258=cut
259
260use strict;
261
262# Make Binary find it's libraries for non standard installations ...
263use Config;
264use File::Basename;
265use vars qw($g_base_dir);
266BEGIN {
267    use FindBin qw($Bin);
268    $g_base_dir = dirname ($Bin);
269}
270use lib "$g_base_dir/lib";
271use lib "$g_base_dir/lib/perl5/$Config{version}";
272use lib "$g_base_dir/lib/perl5/site_perl/$Config{version}";
273
274use File::Spec;
275use File::Basename;
276use IO::Dir;
277
278use Lancelot::GetOpt qw/GetOptions/;
279use Pod::Usage;
280
281use Lancelot::DB;
282use Lancelot::Log qw/log/;
283
284my %opts = ( all => 0 );
285
286GetOptions(\%opts, -defaults, -argvmin => 1, "no list address specified",
287           "query|q?", "set|s?", "import|i?", "delete|d?", "valueonly|h?",
288           "merge|m?", "unmerge|u?", "alias|a?", "into=",
289           "defaults|D?", "modified|M?", "all|A?",
290           "onlynew|n?", "edit|e?", "user|u=");
291
292pod2usage( -message => "$0: need one of --query, --set, --import, --delete, --merge, --unmerge, --alias",
293           -exitvalue => 2 )
294    if $opts{alias} + $opts{query} + $opts{set} + $opts{import}
295           + $opts{delete} + $opts{edit} + $opts{merge} + $opts{unmerge} != 1
296        || (($opts{valueonly} || $opts{defaults} || $opts{modified}
297            || $opts{all}) && !$opts{query})
298        || ($opts{onlynew} && !$opts{import})
299        || ($opts{into} && !$opts{merge});
300
301my $listaddr = shift;
302
303my $db = new Lancelot::DB $listaddr, { user => $opts{user} }
304    or die "$0: error accessing list $listaddr\n";
305
306if ($opts{query}) {
307    my @parameters = @ARGV;
308    if (@ARGV == 0 || (@ARGV == 1 && $ARGV[0] =~ /\.\*$/)) {
309        my ($pattern) = '.';
310        if ($ARGV[0]) {
311            ($pattern = $ARGV[0]) =~ s/\./\\./g; $pattern =~ s/\*/.*/g;
312        }
313        @parameters = grep { /$pattern/o }
314            $db->config_names({ all => $opts{all} });
315        $opts{valueonly} = 0;
316    }
317    foreach my $p (sort @parameters) {
318        my ($v, $status, $default) = $db->get_config_x($p);
319        next if $opts{modified} && $status < 2; 
320        $v = $default if $opts{defaults};
321        print "$p = " unless $opts{valueonly};
322        if ($v =~ /^\s+/ || $v =~ /\s+$/) {
323            $v =~ s/\"/\\\"/g;
324            $v = qq|"$v"|;
325        }
326        print $v, "\n";
327    }
328} elsif ($opts{delete}) {
329    pod2usage("$0: no parameters given\n") if @ARGV == 0;
330    $db->delete_configs(@ARGV);
331} elsif ($opts{set}) {
332    pod2usage("$0: no configs given\n") if @ARGV == 0;
333    $db->set_configs(@ARGV);
334} elsif ($opts{alias}) {
335    if (@ARGV == 0) {
336        # Output aliases for current list
337        my $d = IO::Dir->new(File::Spec->join($ENV{HOME}, ".pl"));
338        if (defined $d) {
339            while (defined ($_ = $d->read)) {
340                next if $_ eq ".default-list";
341                my $dir = File::Spec->join($ENV{HOME}, ".pl", $_);
342                if (-l $dir) {
343                    my $lk = readlink $dir;
344                    print "$_\n" if basename($lk) eq $listaddr
345                        || basename($lk).'@'.basename(dirname($lk)) eq $listaddr;
346                };
347            }
348        }
349    } elsif (@ARGV == 1) {
350        # Set $ARGV[0] up as an alias for the current list
351        my $alias = $ARGV[0];
352        pod2usage("$0: alias name may only contain letters, digits, and \".-_\"\n")
353            if $alias !~ /^[-.\w]+$/;
354        my $lk = File::Spec->join($ENV{HOME}, ".pl", $alias);
355        log "debug", "lk=$lk";
356        pod2usage("$0: alias $alias is otherwise used") if -e $lk && !-l $lk;
357        unlink $lk if -l $lk;
358        symlink $db->get_listdir(), $lk or log "err", "alias: $!";
359    } else {
360        pod2usage("$0: too many arguments\n");
361    }
362} elsif ($opts{import}) {
363    my @lines;
364    my %exist = map { $_ => 1 } $db->config_names;
365    foreach my $line (grep { !/^$/ && !/^\#/ } <>) {
366        my ($name) = $line =~ /^\s*([\.\w]+)/;
367        push @lines, $line unless $opts{onlynew} && $exist{$name};
368    }
369    $db->set_configs(@lines);
370} elsif ($opts{edit}) {
371    my $cmd = $ENV{VISUAL};
372    $cmd ||= $ENV{EDITOR};
373    $cmd ||= "/usr/bin/sensible-editor" if -x "/usr/bin/sensible-editor";
374    $cmd ||= "/usr/bin/vi";
375
376    my $file = File::Spec->join($db->get_listdir, "pl-conf.$$");
377    # Hole Konfiguration nach $file
378
379    if (!system "$cmd $file") {
380        # Zurückschreiben in die Datenbank
381    } else {
382        # Temporäre Datei löschen
383    }
384} elsif ($opts{merge}) {
385    log "debug", "merge $listaddr into $opts{into}";
386    $db->merge_into($opts{into}) or die "$0: error on merge\n";
387} elsif ($opts{unmerge}) {
388    die "$0: unmerge: not implemented yet\n";
389}
Note: See TracBrowser for help on using the browser.