summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Mailman/bin/config_list.py (renamed from bin/config_list)229
-rw-r--r--Mailman/bin/export.py308
-rw-r--r--Mailman/bin/list_lists.py4
-rw-r--r--bin/Makefile.in11
-rwxr-xr-xconfigure3
-rw-r--r--configure.in3
6 files changed, 417 insertions, 141 deletions
diff --git a/bin/config_list b/Mailman/bin/config_list.py
index 25d4fb62a..32daecc6c 100644
--- a/bin/config_list
+++ b/Mailman/bin/config_list.py
@@ -1,6 +1,4 @@
-#! @PYTHON@
-#
-# Copyright (C) 1998-2005 by the Free Software Foundation, Inc.
+# Copyright (C) 1998-2006 by the Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@@ -17,97 +15,92 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
# USA.
-"""Configure a list from a text file description.
-
-Usage: config_list [options] listname
-
-Options:
- --inputfile filename
- -i filename
- Configure the list by assigning each module-global variable in the
- file to an attribute on the list object, then saving the list. The
- named file is loaded with execfile() and must be legal Python code.
- Any variable that isn't already an attribute of the list object is
- ignored (a warning message is printed). See also the -c option.
-
- A special variable named `mlist' is put into the globals during the
- execfile, which is bound to the actual MailList object. This lets you
- do all manner of bizarre thing to the list object, but BEWARE! Using
- this can severely (and possibly irreparably) damage your mailing list!
-
- --outputfile filename
- -o filename
- Instead of configuring the list, print out a list's configuration
- variables in a format suitable for input using this script. In this
- way, you can easily capture the configuration settings for a
- particular list and imprint those settings on another list. filename
- is the file to output the settings to. If filename is `-', standard
- out is used.
-
- --checkonly
- -c
- With this option, the modified list is not actually changed. Only
- useful with -i.
-
- --verbose
- -v
- Print the name of each attribute as it is being changed. Only useful
- with -i.
-
- --help
- -h
- Print this help message and exit.
-
-The options -o and -i are mutually exclusive.
-
-"""
-
-import sys
import re
+import sys
import time
-import getopt
-from types import TupleType
+import optparse
-import paths
-from Mailman import mm_cfg
+from Mailman import Errors
from Mailman import MailList
from Mailman import Utils
-from Mailman import Errors
+from Mailman import Version
from Mailman import i18n
+from Mailman.configuration import config
_ = i18n._
+__i18n_templates__ = True
NL = '\n'
nonasciipat = re.compile(r'[\x80-\xff]')
-def usage(code, msg=''):
- if code:
- fd = sys.stderr
- else:
- fd = sys.stdout
- print >> fd, _(__doc__)
- if msg:
- print >> fd, msg
- sys.exit(code)
+def parseargs():
+ parser = optparse.OptionParser(version=Version.MAILMAN_VERSION,
+ usage=_("""\
+%prog [options] listname
+
+Configure a list from a text file description, or dump a list's configuration
+settings."""))
+ parser.add_option('-i', '--inputfile',
+ metavar='FILENAME', default=None, type='string',
+ help=_("""\
+Configure the list by assigning each module-global variable in the file to an
+attribute on the mailing list object, then save the list. The named file is
+loaded with execfile() and must be legal Python code. Any variable that isn't
+already an attribute of the list object is ignored (a warning message is
+printed). See also the -c option.
+
+A special variable named 'mlist' is put into the globals during the execfile,
+which is bound to the actual MailList object. This lets you do all manner of
+bizarre thing to the list object, but BEWARE! Using this can severely (and
+possibly irreparably) damage your mailing list!
+
+The may not be used with the -o option."""))
+ parser.add_option('-o', '--outputfile',
+ metavar='FILENAME', default=None, type='string',
+ help=_("""\
+Instead of configuring the list, print out a mailing list's configuration
+variables in a format suitable for input using this script. In this way, you
+can easily capture the configuration settings for a particular list and
+imprint those settings on another list. FILENAME is the file to output the
+settings to. If FILENAME is `-', standard out is used.
+
+This may not be used with the -i option."""))
+ parser.add_option('-c', '--checkonly',
+ default=False, action='store_true', help=_("""\
+With this option, the modified list is not actually changed. This is only
+useful with the -i option."""))
+ parser.add_option('-v', '--verbose',
+ default=False, action='store_true', help=_("""\
+Print the name of each attribute as it is being changed. This is only useful
+with the -i option."""))
+ parser.add_option('-C', '--config',
+ help=_('Alternative configuration file to use'))
+ opts, args = parser.parse_args()
+ if len(args) > 1:
+ parser.print_help()
+ parser.error(_('Unexpected arguments'))
+ if not args:
+ parser.error(_('List name is required'))
+ return parser, opts, args
-def do_output(listname, outfile):
- closep = 0
+def do_output(listname, outfile, parser):
+ closep = False
try:
if outfile == '-':
outfp = sys.stdout
else:
outfp = open(outfile, 'w')
- closep = 1
+ closep = True
# Open the specified list unlocked, since we're only reading it.
try:
- mlist = MailList.MailList(listname, lock=0)
+ mlist = MailList.MailList(listname, lock=False)
except Errors.MMListError:
- usage(1, _('No such list: %(listname)s'))
- # Preamble for the config info. PEP263 charset and capture time.
+ parser.error(_('No such list: $listname'))
+ # Preamble for the config info. PEP 263 charset and capture time.
language = mlist.preferred_language
charset = Utils.GetCharSet(language)
i18n.set_language(language)
@@ -116,13 +109,13 @@ def do_output(listname, outfile):
when = time.ctime(time.time())
print >> outfp, _('''\
# -*- python -*-
-# -*- coding: %(charset)s -*-
-## "%(listname)s" mailing list configuration settings
-## captured on %(when)s
+# -*- coding: $charset -*-
+## "$listname" mailing list configuration settings
+## captured on $when
''')
- # get all the list config info. all this stuff is accessible via the
- # web interface
- for k in mm_cfg.ADMIN_CATEGORIES:
+ # Get all the list config info. All this stuff is accessible via the
+ # web interface.
+ for k in config.ADMIN_CATEGORIES:
subcats = mlist.GetConfigSubCategories(k)
if subcats is None:
do_list_categories(mlist, k, None, outfp)
@@ -134,6 +127,7 @@ def do_output(listname, outfile):
outfp.close()
+
def do_list_categories(mlist, k, subcat, outfp):
info = mlist.GetConfigInfo(k, subcat)
label, gui = mlist.GetConfigCategories()[k]
@@ -145,14 +139,14 @@ def do_list_categories(mlist, k, subcat, outfp):
# First, massage the descripton text, which could have obnoxious
# leading whitespace on second and subsequent lines due to
# triple-quoted string nonsense in the source code.
- desc = NL.join([s.lstrip() for s in info[0].split('\n')])
+ desc = NL.join([s.lstrip() for s in info[0].splitlines()])
# Print out the category description
desc = Utils.wrap(desc)
- for line in desc.split('\n'):
+ for line in desc.splitlines():
print >> outfp, '#', line
print >> outfp
for data in info[1:]:
- if not isinstance(data, TupleType):
+ if not isinstance(data, tuple):
continue
varname = data[0]
# Variable could be volatile
@@ -162,7 +156,7 @@ def do_list_categories(mlist, k, subcat, outfp):
# First, massage the descripton text, which could have
# obnoxious leading whitespace on second and subsequent lines
# due to triple-quoted string nonsense in the source code.
- desc = NL.join([s.lstrip() for s in data[-1].split('\n')])
+ desc = NL.join([s.lstrip() for s in data[-1].splitlines()])
# Now strip out all HTML tags
desc = re.sub('<.*?>', '', desc)
# And convert &lt;/&gt; to <>
@@ -178,7 +172,7 @@ def do_list_categories(mlist, k, subcat, outfp):
value = gui.getValue(mlist, vtype, varname, data[2])
if value is None and not varname.startswith('_'):
value = getattr(mlist, varname)
- if vtype in (mm_cfg.String, mm_cfg.Text, mm_cfg.FileUpload):
+ if vtype in (config.String, config.Text, config.FileUpload):
print >> outfp, varname, '=',
lines = value.splitlines()
if not lines:
@@ -197,13 +191,13 @@ def do_list_categories(mlist, k, subcat, outfp):
outfp.write(' """')
outfp.write(NL.join(lines).replace('"', '\\"'))
outfp.write('"""\n')
- elif vtype in (mm_cfg.Radio, mm_cfg.Toggle):
+ elif vtype in (config.Radio, config.Toggle):
print >> outfp, '#'
print >> outfp, '#', _('legal values are:')
# TBD: This is disgusting, but it's special cased
# everywhere else anyway...
if varname == 'subscribe_policy' and \
- not mm_cfg.ALLOW_OPEN_SUBSCRIBE:
+ not config.ALLOW_OPEN_SUBSCRIBE:
i = 1
else:
i = 0
@@ -228,7 +222,7 @@ def getPropertyMap(mlist):
subcats = [(None, None)]
for subcat, sclabel in subcats:
for element in gui.GetConfigInfo(mlist, category, subcat):
- if not isinstance(element, TupleType):
+ if not isinstance(element, tuple):
continue
propname = element[0]
wtype = element[1]
@@ -247,35 +241,36 @@ class FakeDoc:
pass
-def do_input(listname, infile, checkonly, verbose):
+
+def do_input(listname, infile, checkonly, verbose, parser):
fakedoc = FakeDoc()
- # open the specified list locked, unless checkonly is set
+ # Open the specified list locked, unless checkonly is set
try:
mlist = MailList.MailList(listname, lock=not checkonly)
except Errors.MMListError, e:
- usage(1, _('No such list "%(listname)s"\n%(e)s'))
- savelist = 0
+ parser.error(_('No such list "$listname"\n$e'))
+ savelist = False
guibyprop = getPropertyMap(mlist)
try:
globals = {'mlist': mlist}
# Any exception that occurs in execfile() will cause the list to not
# be saved, but any other problems are not save-fatal.
execfile(infile, globals)
- savelist = 1
+ savelist = True
for k, v in globals.items():
if k in ('mlist', '__builtins__'):
continue
if not hasattr(mlist, k):
- print >> sys.stderr, _('attribute "%(k)s" ignored')
+ print >> sys.stderr, _('attribute "$k" ignored')
continue
if verbose:
- print >> sys.stderr, _('attribute "%(k)s" changed')
+ print >> sys.stderr, _('attribute "$k" changed')
missing = []
gui, wtype = guibyprop.get(k, (missing, missing))
if gui is missing:
# This isn't an official property of the list, but that's
# okay, we'll just restore it the old fashioned way
- print >> sys.stderr, _('Non-standard property restored: %(k)s')
+ print >> sys.stderr, _('Non-standard property restored: $k')
setattr(mlist, k, v)
else:
# BAW: This uses non-public methods. This logic taken from
@@ -283,10 +278,10 @@ def do_input(listname, infile, checkonly, verbose):
try:
validval = gui._getValidValue(mlist, k, wtype, v)
except ValueError:
- print >> sys.stderr, _('Invalid value for property: %(k)s')
+ print >> sys.stderr, _('Invalid value for property: $k')
except Errors.EmailAddressError:
print >> sys.stderr, _(
- 'Bad email address for option %(k)s: %(v)s')
+ 'Bad email address for option $k: $v')
else:
# BAW: Horrible hack, but then this is special cased
# everywhere anyway. :( Privacy._setValue() knows that
@@ -316,45 +311,21 @@ def do_input(listname, infile, checkonly, verbose):
def main():
- try:
- opts, args = getopt.getopt(
- sys.argv[1:], 'ci:o:vh',
- ['checkonly', 'inputfile=', 'outputfile=', 'verbose', 'help'])
- except getopt.error, msg:
- usage(1, msg)
-
- # defaults
- infile = None
- outfile = None
- checkonly = 0
- verbose = 0
- for opt, arg in opts:
- if opt in ('-h', '--help'):
- usage(0)
- elif opt in ('-o', '--outputfile'):
- outfile = arg
- elif opt in ('-i', '--inputfile'):
- infile = arg
- elif opt in ('-c', '--checkonly'):
- checkonly = 1
- elif opt in ('-v', '--verbose'):
- verbose = 1
-
- # sanity check
- if infile is not None and outfile is not None:
- usage(1, _('Only one of -i or -o is allowed'))
- if infile is None and outfile is None:
- usage(1, _('One of -i or -o is required'))
+ parser, opts, args = parseargs()
+ config.load(opts.config)
+ listname = args[0]
- # get the list name
- if len(args) <> 1:
- usage(1, _('List name is required'))
- listname = args[0].lower().strip()
+ # Sanity check
+ if opts.inputfile and opts.outputfile:
+ parser.error(_('Only one of -i or -o is allowed'))
+ if not opts.inputfile and not opts.outputfile:
+ parser.error(_('One of -i or -o is required'))
- if outfile:
- do_output(listname, outfile)
+ if opts.outputfile:
+ do_output(listname, opts.outputfile, parser)
else:
- do_input(listname, infile, checkonly, verbose)
+ do_input(listname, opts.inputfile, opts.checkonly,
+ opts.verbose, parser)
diff --git a/Mailman/bin/export.py b/Mailman/bin/export.py
new file mode 100644
index 000000000..4a72c4e82
--- /dev/null
+++ b/Mailman/bin/export.py
@@ -0,0 +1,308 @@
+# Copyright (C) 2006 by the Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+# USA.
+
+"""Export an XML representation of a mailing list."""
+
+import sys
+import datetime
+import optparse
+
+from xml.sax.saxutils import escape
+
+from Mailman import Defaults
+from Mailman import Errors
+from Mailman import MemberAdaptor
+from Mailman import Utils
+from Mailman import Version
+from Mailman.MailList import MailList
+from Mailman.configuration import config
+from Mailman.i18n import _
+
+__i18n_templates__ = True
+
+SPACE = ' '
+DOLLAR_STRINGS = ('msg_header', 'msg_footer',
+ 'digest_header', 'digest_footer',
+ 'autoresponse_postings_text',
+ 'autoresponse_admin_text',
+ 'autoresponse_request_text')
+
+
+
+class Indenter:
+ def __init__(self, fp, indentwidth=4):
+ self._fp = fp
+ self._indent = 0
+ self._width = indentwidth
+
+ def indent(self):
+ self._indent += 1
+
+ def dedent(self):
+ self._indent -= 1
+ assert self._indent >= 0
+
+ def write(self, s):
+ self._fp.write(self._indent * self._width * ' ')
+ self._fp.write(s)
+
+
+
+class XMLDumper(object):
+ def __init__(self, fp):
+ self._fp = Indenter(fp)
+ self._tagbuffer = None
+ self._stack = []
+
+ def _makeattrs(self, tagattrs):
+ # The attribute values might contain angle brackets. They might also
+ # be None.
+ attrs = []
+ for k, v in tagattrs.items():
+ if v is None:
+ v = ''
+ else:
+ v = escape(str(v))
+ attrs.append('%s="%s"' % (k, v))
+ return SPACE.join(attrs)
+
+ def _flush(self, more=True):
+ if not self._tagbuffer:
+ return
+ name, attributes = self._tagbuffer
+ self._tagbuffer = None
+ if attributes:
+ attrstr = ' ' + self._makeattrs(attributes)
+ else:
+ attrstr = ''
+ if more:
+ print >> self._fp, '<%s%s>' % (name, attrstr)
+ self._fp.indent()
+ self._stack.append(name)
+ else:
+ print >> self._fp, '<%s%s/>' % (name, attrstr)
+
+ # Use this method when you know you have sub-elements.
+ def _push_element(self, _name, **_tagattrs):
+ self._flush()
+ self._tagbuffer = (_name, _tagattrs)
+
+ def _pop_element(self, _name):
+ buffered = bool(self._tagbuffer)
+ self._flush(more=False)
+ if not buffered:
+ name = self._stack.pop()
+ assert name == _name, 'got: %s, expected: %s' % (_name, name)
+ self._fp.dedent()
+ print >> self._fp, '</%s>' % name
+
+ # Use this method when you do not have sub-elements
+ def _element(self, _name, _value=None, **_attributes):
+ self._flush()
+ if _attributes:
+ attrs = ' ' + self._makeattrs(_attributes)
+ else:
+ attrs = ''
+ if _value is None:
+ print >> self._fp, '<%s%s/>' % (_name, attrs)
+ else:
+ # The value might contain angle brackets.
+ value = escape(str(_value))
+ print >> self._fp, '<%s%s>%s</%s>' % (_name, attrs, value, _name)
+
+ def _do_list_categories(self, mlist, k, subcat=None):
+ is_converted = bool(getattr(mlist, 'use_dollar_strings', False))
+ info = mlist.GetConfigInfo(k, subcat)
+ label, gui = mlist.GetConfigCategories()[k]
+ if info is None:
+ return
+ for data in info[1:]:
+ if not isinstance(data, tuple):
+ continue
+ varname = data[0]
+ # Variable could be volatile
+ if varname.startswith('_'):
+ continue
+ vtype = data[1]
+ # Munge the value based on its type
+ value = None
+ if hasattr(gui, 'getValue'):
+ value = gui.getValue(mlist, vtype, varname, data[2])
+ if value is None:
+ value = getattr(mlist, varname)
+ # Do %-string to $-string conversions if the list hasn't already
+ # been converted.
+ if varname == 'use_dollar_strings':
+ continue
+ if not is_converted and varname in DOLLAR_STRINGS:
+ value = Utils.to_dollar(value)
+ if isinstance(value, list):
+ self._push_element('option', name=varname)
+ for v in value:
+ self._element('value', v)
+ self._pop_element('option')
+ else:
+ self._element('option', name=varname, value=value)
+
+ def _dump_list(self, mlist, with_passwords):
+ # Write list configuration values
+ self._push_element('list', name=mlist.fqdn_listname)
+ self._element('language', mlist.preferred_language)
+ for k in config.ADMIN_CATEGORIES:
+ subcats = mlist.GetConfigSubCategories(k)
+ if subcats is None:
+ self._do_list_categories(mlist, k)
+ else:
+ for subcat in [t[0] for t in subcats]:
+ self._do_list_categories(mlist, k, subcat)
+ # Write membership
+ self._push_element('roster')
+ digesters = set(mlist.getDigestMemberKeys())
+ for member in sorted(mlist.getMembers()):
+ attrs = dict(id=member)
+ cased = mlist.getMemberCPAddress(member)
+ if cased <> member:
+ dict['original'] = cased
+ self._push_element('member', **attrs)
+ self._element('realname', mlist.getMemberName(member))
+ if with_passwords:
+ self._element('password', mlist.getMemberPassword(member))
+ self._element('language', mlist.getMemberLanguage(member))
+ # Delivery status, combined with the type of delivery
+ attrs = {}
+ status = mlist.getDeliveryStatus(member)
+ if status == MemberAdaptor.ENABLED:
+ attrs['status'] = 'enabled'
+ else:
+ attrs['status'] = 'disabled'
+ attrs['reason'] = {MemberAdaptor.BYUSER : 'byuser',
+ MemberAdaptor.BYADMIN : 'byadmin',
+ MemberAdaptor.BYBOUNCE : 'bybounce',
+ }.get(mlist.getDeliveryStatus(member),
+ 'unknown')
+ if member in digesters:
+ if mlist.getMemberOption('plain'):
+ attrs['delivery'] = 'plain'
+ else:
+ attrs['delivery'] = 'mime'
+ else:
+ attrs['delivery'] = 'regular'
+ changed = mlist.getDeliveryStatusChangeTime(member)
+ if changed:
+ when = datetime.datetime.fromtimestamp(changed)
+ attrs['changed'] = when.isoformat()
+ self._element('delivery', **attrs)
+ self._push_element('options')
+ for option, flag in Defaults.OPTINFO.items():
+ # Digest/Regular delivery flag must be handled separately
+ if option in ('digest', 'plain'):
+ continue
+ value = mlist.getMemberOption(member, flag)
+ self._element(option, value)
+ self._pop_element('options')
+ topics = mlist.getMemberTopics(member)
+ if not topics:
+ self._element('topics')
+ else:
+ self._push_element('topics')
+ for topic in topics:
+ self._element('topic', topic)
+ self._pop_element('topics')
+ self._pop_element('member')
+ self._pop_element('roster')
+ self._pop_element('list')
+
+ def dump(self, listnames, with_passwords=False):
+ print >> self._fp, '<?xml version="1.0" encoding="UTF-8"?>'
+ self._push_element('mailman', **{
+ 'xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance',
+ 'xsi:noNamespaceSchemaLocation': 'ssi-1.0.xsd',
+ })
+ for listname in sorted(listnames):
+ try:
+ mlist = MailList(listname, lock=False)
+ except Errors.MMUnknownListError:
+ print >> sys.stderr, _('No such list: $listname')
+ continue
+ self._dump_list(mlist, with_passwords)
+ self._pop_element('mailman')
+
+ def close(self):
+ while self._stack:
+ self._pop_element()
+
+
+
+def parseargs():
+ parser = optparse.OptionParser(version=Version.MAILMAN_VERSION,
+ usage=_("""\
+%prog [options]
+
+Export the configuration and members of a mailing list in XML format."""))
+ parser.add_option('-o', '--outputfile',
+ metavar='FILENAME', default=None, type='string',
+ help=_("""\
+Output XML to FILENAME. If not given, or if FILENAME is '-', standard out is
+used."""))
+ parser.add_option('-p', '--with-passwords',
+ default=False, action='store_true', help=_("""\
+With this option, user passwords are included in cleartext. For this reason,
+the default is to not include passwords."""))
+ parser.add_option('-l', '--listname',
+ default=[], action='append', type='string',
+ dest='listnames', help=_("""\
+The list to include in the output. If not given, then all mailing lists are
+included in the XML output. Multiple -l flags may be given."""))
+ parser.add_option('-C', '--config',
+ help=_('Alternative configuration file to use'))
+ opts, args = parser.parse_args()
+ if args:
+ parser.print_help()
+ parser.error(_('Unexpected arguments'))
+ return parser, opts, args
+
+
+
+def main():
+ parser, opts, args = parseargs()
+ config.load(opts.config)
+
+ if opts.outputfile in (None, '-'):
+ fp = sys.stdout
+ else:
+ fp = open(opts.outputfile, 'w')
+
+ try:
+ dumper = XMLDumper(fp)
+ if opts.listnames:
+ listnames = []
+ for listname in opts.listnames:
+ if '@' not in listname:
+ listname = '%s@%s' % (listname, config.DEFAULT_EMAIL_HOST)
+ listnames.append(listname)
+ else:
+ listnames = Utils.list_names()
+ dumper.dump(listnames, opts.with_passwords)
+ dumper.close()
+ finally:
+ if fp is not sys.stdout:
+ fp.close()
+
+
+
+if __name__ == '__main__':
+ main()
diff --git a/Mailman/bin/list_lists.py b/Mailman/bin/list_lists.py
index b766f85bc..c9480217d 100644
--- a/Mailman/bin/list_lists.py
+++ b/Mailman/bin/list_lists.py
@@ -15,7 +15,6 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
# USA.
-import sys
import optparse
from Mailman import Defaults
@@ -59,8 +58,7 @@ ignored when -b is given."""))
opts, args = parser.parse_args()
if args:
parser.print_help()
- print >> sys.stderr, _('Unexpected arguments')
- sys.exit(1)
+ parser.error(_('Unexpected arguments'))
return parser, opts, args
diff --git a/bin/Makefile.in b/bin/Makefile.in
index 1aeb68923..2256cfd60 100644
--- a/bin/Makefile.in
+++ b/bin/Makefile.in
@@ -47,16 +47,17 @@ SHELL= /bin/sh
SCRIPTS= mmshell \
remove_members clone_member \
sync_members check_db withlist \
- config_list dumpdb cleanarch \
+ dumpdb cleanarch \
list_admins \
fix_url.py convert.py transcheck \
msgfmt.py discard \
reset_pw.py templ2pot.py po2templ.py
-LN_SCRIPTS= add_members arch change_pw check_perms find_member \
- genaliases inject list_lists list_members list_owners \
- mailmanctl mmsitepass newlist qrunner rmlist show_qfiles \
- show_mm_cfg testall unshunt update version
+LN_SCRIPTS= add_members arch change_pw check_perms config_list \
+ export find_member genaliases inject list_lists \
+ list_members list_owners mailmanctl mmsitepass newlist \
+ qrunner rmlist show_qfiles show_mm_cfg testall unshunt \
+ update version
BUILDDIR= ../build/bin
diff --git a/configure b/configure
index cc586232a..6c82b0051 100755
--- a/configure
+++ b/configure
@@ -1,5 +1,5 @@
#! /bin/sh
-# From configure.in Revision: 8038 .
+# From configure.in Revision: 8040 .
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.59 for GNU Mailman 2.2.0a0.
#
@@ -4287,7 +4287,6 @@ done
SCRIPTS="build/bin/check_db:bin/check_db \
build/bin/cleanarch:bin/cleanarch \
build/bin/clone_member:bin/clone_member \
-build/bin/config_list:bin/config_list \
build/bin/convert.py:bin/convert.py \
build/bin/discard:bin/discard \
build/bin/dumpdb:bin/dumpdb \
diff --git a/configure.in b/configure.in
index fd6e793dc..d5017718d 100644
--- a/configure.in
+++ b/configure.in
@@ -16,7 +16,7 @@
# USA.
dnl Process this file with autoconf to produce a configure script.
-AC_REVISION($Revision: 8040 $)
+AC_REVISION($Revision: 8051 $)
AC_PREREQ(2.0)
AC_INIT([GNU Mailman], [2.2.0a0])
@@ -595,7 +595,6 @@ AC_DEFUN(MM_SCRIPTS, [dnl
bin/check_db \
bin/cleanarch \
bin/clone_member \
-bin/config_list \
bin/convert.py \
bin/discard \
bin/dumpdb \