diff options
| -rw-r--r-- | Mailman/bin/add_members.py | 8 | ||||
| -rw-r--r-- | Mailman/bin/arch.py | 14 | ||||
| -rw-r--r-- | Mailman/bin/bumpdigests.py | 8 | ||||
| -rw-r--r-- | Mailman/bin/change_pw.py | 10 | ||||
| -rwxr-xr-x | Mailman/bin/checkdbs.py | 16 | ||||
| -rw-r--r-- | Mailman/bin/config_list.py | 4 | ||||
| -rw-r--r-- | Mailman/bin/disabled.py | 16 | ||||
| -rw-r--r-- | Mailman/bin/find_member.py | 12 | ||||
| -rw-r--r-- | Mailman/bin/gate_news.py | 31 | ||||
| -rw-r--r-- | Mailman/bin/list_members.py | 10 | ||||
| -rw-r--r-- | Mailman/bin/list_owners.py | 8 | ||||
| -rw-r--r-- | Mailman/bin/nightly_gzip.py | 16 | ||||
| -rw-r--r-- | Mailman/bin/senddigests.py | 8 | ||||
| -rw-r--r-- | Mailman/bin/show_qfiles.py | 8 | ||||
| -rw-r--r-- | Mailman/configuration.py | 287 | ||||
| -rw-r--r-- | Mailman/loginit.py | 262 |
16 files changed, 388 insertions, 330 deletions
diff --git a/Mailman/bin/add_members.py b/Mailman/bin/add_members.py index 2c0ffa868..ab4ecba77 100644 --- a/Mailman/bin/add_members.py +++ b/Mailman/bin/add_members.py @@ -26,8 +26,9 @@ from Mailman import Errors from Mailman import MailList from Mailman import Message from Mailman import Utils +from Mailman import Version from Mailman import i18n -from Mailman import mm_cfg +from Mailman.configuration import config _ = i18n._ __i18n_templates__ = True @@ -35,7 +36,7 @@ __i18n_templates__ = True def parseargs(): - parser = optparse.OptionParser(version=mm_cfg.MAILMAN_VERSION, + parser = optparse.OptionParser(version=Version.MAILMAN_VERSION, usage=_("""\ %prog [options] listname @@ -62,6 +63,8 @@ whatever the list's 'send_welcome_msg' setting is.""")) Set whether or not to send the list administrators a notification on the success/failure of these subscriptions, overriding whatever the list's 'admin_notify_mchanges' setting is.""")) + parser.add_option('-C', '--config', + help=_('Alternative configuration file to use')) opts, args = parser.parse_args() if not args: parser.print_help() @@ -156,6 +159,7 @@ def addall(mlist, members, digest, ack, outfp): def main(): parser, opts, args = parseargs() + config.load(opts.config) listname = args[0].lower().strip() try: diff --git a/Mailman/bin/arch.py b/Mailman/bin/arch.py index 3d3036460..2c98ba8c0 100644 --- a/Mailman/bin/arch.py +++ b/Mailman/bin/arch.py @@ -22,21 +22,20 @@ import shutil import optparse from Mailman import Errors +from Mailman import Version from Mailman import i18n -from Mailman import mm_cfg from Mailman.Archiver.HyperArch import HyperArchive from Mailman.LockFile import LockFile from Mailman.MailList import MailList +from Mailman.configuration import config _ = i18n._ -i18n.set_language(mm_cfg.DEFAULT_SERVER_LANGUAGE) - __i18n_templates__ = True def parseargs(): - parser = optparse.OptionParser(version=mm_cfg.MAILMAN_VERSION, + parser = optparse.OptionParser(version=Version.MAILMAN_VERSION, usage=_("""\ %%prog [options] listname [mbox] @@ -73,6 +72,8 @@ End indexing at article M. This script is not very efficient with respect to memory management, and for large archives, it may not be possible to index the mbox entirely. For that reason, you can specify the start and end article numbers.""")) + parser.add_option('-C', '--config', + help=_('Alternative configuration file to use')) opts, args = parser.parse_args() if len(args) < 1: parser.print_help() @@ -88,6 +89,9 @@ numbers.""")) def main(): parser, opts, args = parseargs() + config.load(opts.config) + + i18n.set_language(config.DEFAULT_SERVER_LANGUAGE) listname = args[0].lower().strip() if len(args) < 2: @@ -119,7 +123,7 @@ def main(): # XXX This may not be necessary because I think we lay claim to the # list lock up above, although that may be too short to be of use (and # maybe we don't really want to lock the list anyway). - lockfile = os.path.join(mm_cfg.LOCK_DIR, mlist._internal_name) + \ + lockfile = os.path.join(config.LOCK_DIR, mlist._internal_name) + \ '.archiver.lock' # set the lock lifetime to 3 hours. XXX is this reasonable??? lock = LockFile(lockfile, lifetime=3*60*60) diff --git a/Mailman/bin/bumpdigests.py b/Mailman/bin/bumpdigests.py index fe63410d6..151a9fa3a 100644 --- a/Mailman/bin/bumpdigests.py +++ b/Mailman/bin/bumpdigests.py @@ -21,7 +21,8 @@ import optparse from Mailman import Errors from Mailman import MailList from Mailman import Utils -from Mailman import mm_cfg +from Mailman import Version +from Mailman.configuration import config from Mailman.i18n import _ # Work around known problems with some RedHat cron daemons @@ -33,13 +34,15 @@ __i18n_templates__ = True def parseargs(): - parser = optparse.OptionParser(version=mm_cfg.MAILMAN_VERSION, + parser = optparse.OptionParser(version=Version.MAILMAN_VERSION, usage=_("""\ %prog [options] [listname ...] Increment the digest volume number and reset the digest number to one. All the lists named on the command line are bumped. If no list names are given, all lists are bumped.""")) + parser.add_option('-C', '--config', + help=_('Alternative configuration file to use')) opts, args = parser.parse_args() return opts, args, parser @@ -47,6 +50,7 @@ all lists are bumped.""")) def main(): opts, args, parser = parseargs() + config.load(opts.config) listnames = set(args or Utils.list_names()) if not listnames: diff --git a/Mailman/bin/change_pw.py b/Mailman/bin/change_pw.py index d77dd9787..fa0289907 100644 --- a/Mailman/bin/change_pw.py +++ b/Mailman/bin/change_pw.py @@ -23,8 +23,9 @@ from Mailman import Errors from Mailman import MailList from Mailman import Message from Mailman import Utils +from Mailman import Version from Mailman import i18n -from Mailman import mm_cfg +from Mailman.configuration import config _ = i18n._ __i18n_templates__ = True @@ -34,7 +35,7 @@ SPACE = ' ' def parseargs(): - parser = optparse.OptionParser(version=mm_cfg.MAILMAN_VERSION, + parser = optparse.OptionParser(version=Version.MAILMAN_VERSION, usage=_("""\ %%prog [options] @@ -75,6 +76,8 @@ not given, lists will be assigned a randomly generated new password.""")) Don't notify list owners of the new password. You'll have to have some other way of letting the list owners know the new password (presumably out-of-band).""")) + parser.add_option('-C', '--config', + help=_('Alternative configuration file to use')) opts, args = parser.parse_args() if args: parser.print_help() @@ -107,6 +110,7 @@ def openlist(listname): def main(): parser, opts, args = parseargs() + config.load(opts.config) # Cull duplicates domains = set(opts.domains) @@ -135,7 +139,7 @@ def main(): try: if opts.password is None: randompw = Utils.MakeRandomPassword( - mm_cfg.ADMIN_PASSWORD_LENGTH) + config.ADMIN_PASSWORD_LENGTH) shapassword = sha.new(randompw).hexdigest() notifypassword = randompw else: diff --git a/Mailman/bin/checkdbs.py b/Mailman/bin/checkdbs.py index ebcbdb177..a4ff2400a 100755 --- a/Mailman/bin/checkdbs.py +++ b/Mailman/bin/checkdbs.py @@ -24,12 +24,11 @@ from email.Charset import Charset from Mailman import MailList from Mailman import Message from Mailman import Utils +from Mailman import Version from Mailman import i18n -from Mailman import mm_cfg +from Mailman.configuration import config _ = i18n._ -i18n.set_language(mm_cfg.DEFAULT_SERVER_LANGUAGE) - __i18n_templates__ = True # Work around known problems with some RedHat cron daemons @@ -42,11 +41,13 @@ now = time.time() def parseargs(): - parser = optparse.OptionParser(version=mm_cfg.MAILMAN_VERSION, + parser = optparse.OptionParser(version=Version.MAILMAN_VERSION, usage=_("""\ %prog [options] Check for pending admin requests and mail the list owners if necessary.""")) + parser.add_option('-C', '--config', + help=_('Alternative configuration file to use')) opts, args = parser.parse_args() if args: parser.print_help() @@ -113,12 +114,12 @@ Cause: $reason""")) def auto_discard(mlist): # Discard old held messages discard_count = 0 - expire = mm_cfg.days(mlist.max_days_to_hold) + expire = config.days(mlist.max_days_to_hold) heldmsgs = mlist.GetHeldMessageIds() if expire and heldmsgs: for id in heldmsgs: if now - mlist.GetRecord(id)[0] > expire: - mlist.HandleRequest(id, mm_cfg.DISCARD) + mlist.HandleRequest(id, config.DISCARD) discard_count += 1 mlist.Save() return discard_count @@ -127,6 +128,9 @@ def auto_discard(mlist): def main(): opts, args, parser = parseargs() + config.load(opts.config) + + i18n.set_language(config.DEFAULT_SERVER_LANGUAGE) for name in Utils.list_names(): # The list must be locked in order to open the requests database diff --git a/Mailman/bin/config_list.py b/Mailman/bin/config_list.py index 32daecc6c..c2af58e16 100644 --- a/Mailman/bin/config_list.py +++ b/Mailman/bin/config_list.py @@ -290,7 +290,7 @@ def do_input(listname, infile, checkonly, verbose, parser): # one. But we really do provide [0..3] so we need to undo # the hack that _setValue adds. :( :( if k == 'subscribe_policy' and \ - not mm_cfg.ALLOW_OPEN_SUBSCRIBE: + not config.ALLOW_OPEN_SUBSCRIBE: validval -= 1 # BAW: Another horrible hack. This one is just too hard # to fix in a principled way in Mailman 2.1 @@ -299,7 +299,7 @@ def do_input(listname, infile, checkonly, verbose, parser): # transforms the value into a list of one item. validval = validval[0] validval = [bitfield for bitfield, bitval - in mm_cfg.OPTINFO.items() + in config.OPTINFO.items() if validval & bitval] gui._setValue(mlist, k, validval, fakedoc) # BAW: when to do gui._postValidate()??? diff --git a/Mailman/bin/disabled.py b/Mailman/bin/disabled.py index cc9205c19..4b82b8126 100644 --- a/Mailman/bin/disabled.py +++ b/Mailman/bin/disabled.py @@ -24,9 +24,10 @@ from Mailman import MailList from Mailman import MemberAdaptor from Mailman import Pending from Mailman import Utils +from Mailman import Version from Mailman import loginit -from Mailman import mm_cfg from Mailman.Bouncer import _BounceInfo +from Mailman.configuration import config from Mailman.i18n import _ __i18n_templates__ = True @@ -35,10 +36,6 @@ __i18n_templates__ = True import signal signal.signal(signal.SIGCHLD, signal.SIG_DFL) -loginit.initialize(propagate=True) -elog = logging.getLogger('mailman.error') -blog = logging.getLogger('mailman.bounce') - ALL = (MemberAdaptor.BYBOUNCE, MemberAdaptor.BYADMIN, MemberAdaptor.BYUSER, @@ -62,7 +59,7 @@ def who_callback(option, opt, value, parser): def parseargs(): - parser = optparse.OptionParser(version=mm_cfg.MAILMAN_VERSION, + parser = optparse.OptionParser(version=Version.MAILMAN_VERSION, usage=_("""\ %prog [options] @@ -110,6 +107,8 @@ notification yet.""")) dest='listnames', action='append', default=[], type='string', help=_("""\ Process only the given list, otherwise do all lists.""")) + parser.add_option('-C', '--config', + help=_('Alternative configuration file to use')) opts, args = parser.parse_args() return opts, args, parser @@ -117,6 +116,11 @@ Process only the given list, otherwise do all lists.""")) def main(): opts, args, parser = parseargs() + config.load(opts.config) + + loginit.initialize(propagate=True) + elog = logging.getLogger('mailman.error') + blog = logging.getLogger('mailman.bounce') listnames = set(opts.listnames or Utils.list_names()) who = tuple(opts.who) diff --git a/Mailman/bin/find_member.py b/Mailman/bin/find_member.py index e249fb30b..34d9f5103 100644 --- a/Mailman/bin/find_member.py +++ b/Mailman/bin/find_member.py @@ -22,7 +22,8 @@ import optparse from Mailman import Errors from Mailman import MailList from Mailman import Utils -from Mailman import mm_cfg +from Mailman import Version +from Mailman.configuration import config from Mailman.i18n import _ @@ -34,7 +35,7 @@ AS_OWNER = 0x02 def parseargs(): - parser = optparse.OptionParser(version=mm_cfg.MAILMAN_VERSION, + parser = optparse.OptionParser(version=Version.MAILMAN_VERSION, usage=_("""\ %prog [options] regex [regex ...] @@ -63,20 +64,23 @@ displayed.""")) parser.add_option('-w', '--owners', default=False, action='store_true', help=_('Search list owners as well as members')) + parser.add_option('-C', '--config', + help=_('Alternative configuration file to use')) opts, args = parser.parse_args() if not args: parser.print_help() print >> sys.stderr, _('Search regular expression required') sys.exit(1) - if not opts.listnames and opts.excludes: - opts.listnames = Utils.list_names() return parser, opts, args def main(): parser, opts, args = parseargs() + config.load(opts.config) + if not opts.listnames: + opts.listnames = Utils.list_names() includes = set(listname.lower() for listname in opts.listnames) excludes = set(listname.lower() for listname in opts.excludes) listnames = includes - excludes diff --git a/Mailman/bin/gate_news.py b/Mailman/bin/gate_news.py index 4c55273cd..7046fe93f 100644 --- a/Mailman/bin/gate_news.py +++ b/Mailman/bin/gate_news.py @@ -30,22 +30,19 @@ from Mailman import LockFile from Mailman import MailList from Mailman import Message from Mailman import Utils +from Mailman import Version from Mailman import loginit -from Mailman import mm_cfg from Mailman.Queue.sbcache import get_switchboard +from Mailman.configuration import config from Mailman.i18n import _ # Work around known problems with some RedHat cron daemons import signal signal.signal(signal.SIGCHLD, signal.SIG_DFL) -GATENEWS_LOCK_FILE = os.path.join(mm_cfg.LOCK_DIR, 'gate_news.lock') - -LOCK_LIFETIME = mm_cfg.hours(2) NL = '\n' -loginit.initialize(propagate=True) -log = logging.getLogger('mailman.fromusenet') +log = None class _ContinueLoop(Exception): pass @@ -55,11 +52,13 @@ __i18n_templates__ = True def parseargs(): - parser = optparse.OptionParser(version=mm_cfg.MAILMAN_VERSION, + parser = optparse.OptionParser(version=Version.MAILMAN_VERSION, usage=_("""\ %prog [options] Poll the NNTP servers for messages to be gatewayed to mailing lists.""")) + parser.add_option('-C', '--config', + help=_('Alternative configuration file to use')) opts, args = parser.parse_args() if args: parser.print_help() @@ -81,8 +80,8 @@ def open_newsgroup(mlist): try: conn = nntplib.NNTP(nntp_host, nntp_port, readermode=True, - user=mm_cfg.NNTP_USERNAME, - password=mm_cfg.NNTP_PASSWORD) + user=config.NNTP_USERNAME, + password=config.NNTP_PASSWORD) except (socket.error, nntplib.NNTPError, IOError), e: log.error('error opening connection to nntp_host: %s\n%s', mlist.nntp_host, e) @@ -149,7 +148,7 @@ def poll_newsgroup(mlist, conn, first, last, glock): del msg['To'] msg['To'] = mlist.GetListEmail() # Post the message to the locked list - inq = get_switchboard(mm_cfg.INQUEUE_DIR) + inq = get_switchboard(config.INQUEUE_DIR) inq.enqueue(msg, listname=mlist.internal_name(), fromusenet=True) @@ -186,7 +185,7 @@ def process_lists(glock): try: try: if watermark is None: - mlist.Lock(timeout=mm_cfg.LIST_LOCK_TIMEOUT) + mlist.Lock(timeout=config.LIST_LOCK_TIMEOUT) # This is the first time we've tried to gate this # newsgroup. We essentially do a mass catch-up, otherwise # we'd flood the mailing list. @@ -204,7 +203,7 @@ def process_lists(glock): if start > last: log.info('nothing new for list %s', listname) else: - mlist.Lock(timeout=mm_cfg.LIST_LOCK_TIMEOUT) + mlist.Lock(timeout=config.LIST_LOCK_TIMEOUT) log.info('gating %s articles [%d..%d]', listname, start, last) # Use last+1 because poll_newsgroup() employes a for @@ -223,6 +222,14 @@ def process_lists(glock): def main(): opts, args, parser = parseargs() + config.load(opts.config) + + GATENEWS_LOCK_FILE = os.path.join(config.LOCK_DIR, 'gate_news.lock') + LOCK_LIFETIME = config.hours(2) + + loginit.initialize(propagate=True) + log = logging.getLogger('mailman.fromusenet') + lock = LockFile.LockFile(GATENEWS_LOCK_FILE, # It's okay to hijack this lifetime=LOCK_LIFETIME) diff --git a/Mailman/bin/list_members.py b/Mailman/bin/list_members.py index 1239b955f..eb6a02f92 100644 --- a/Mailman/bin/list_members.py +++ b/Mailman/bin/list_members.py @@ -24,7 +24,8 @@ from Mailman import Errors from Mailman import MailList from Mailman import MemberAdaptor from Mailman import Utils -from Mailman import mm_cfg +from Mailman import Version +from Mailman.configuration import config from Mailman.i18n import _ __i18n_templates__ = True @@ -45,7 +46,7 @@ KINDCHOICES = set(('mime', 'plain', 'any')) def parseargs(): - parser = optparse.OptionParser(version=mm_cfg.MAILMAN_VERSION, + parser = optparse.OptionParser(version=Version.MAILMAN_VERSION, usage=_("""\ %prog [options] listname @@ -89,6 +90,8 @@ Print only the addresses in the membership list that are invalid. Ignores -r, default=False, action='store_true', help=_("""\ Print addresses which are stored as Unicode objects instead of normal string objects. Ignores -r, -d, -n.""")) + parser.add_option('-C', '--config', + help=_('Alternative configuration file to use')) opts, args = parser.parse_args() if not args: parser.print_help() @@ -154,6 +157,7 @@ def whymatches(mlist, addr, why): def main(): parser, opts, args = parseargs() + config.load(opts.config) listname = args[0].lower().strip() if opts.output: @@ -210,7 +214,7 @@ def main(): if opts.nomail and not whymatches(mlist, addr, opts.why): continue # Filter out digest kinds - if mlist.getMemberOption(addr, mm_cfg.DisableMime): + if mlist.getMemberOption(addr, config.DisableMime): # They're getting plain text digests if opts.kind == 'mime': continue diff --git a/Mailman/bin/list_owners.py b/Mailman/bin/list_owners.py index 2ff6a9d53..d3feeef97 100644 --- a/Mailman/bin/list_owners.py +++ b/Mailman/bin/list_owners.py @@ -19,8 +19,9 @@ import sys import optparse from Mailman import Utils -from Mailman import mm_cfg +from Mailman import Version from Mailman.MailList import MailList +from Mailman.configuration import config from Mailman.i18n import _ __i18n_templates__ = True @@ -28,7 +29,7 @@ __i18n_templates__ = True def parseargs(): - parser = optparse.OptionParser(version=mm_cfg.MAILMAN_VERSION, + parser = optparse.OptionParser(version=Version.MAILMAN_VERSION, usage=_("""\ %prog [options] [listname ...] @@ -43,6 +44,8 @@ address.""")) parser.add_option('-m', '--moderators', default=False, action='store_true', help=_('Include the list moderators in the output.')) + parser.add_option('-C', '--config', + help=_('Alternative configuration file to use')) opts, args = parser.parse_args() return parser, opts, args @@ -50,6 +53,7 @@ address.""")) def main(): parser, opts, args = parseargs() + config.load(opts.config) listnames = args or Utils.list_names() bylist = {} diff --git a/Mailman/bin/nightly_gzip.py b/Mailman/bin/nightly_gzip.py index 037612adb..f55b21493 100644 --- a/Mailman/bin/nightly_gzip.py +++ b/Mailman/bin/nightly_gzip.py @@ -26,9 +26,10 @@ try: except ImportError: sys.exit(0) -from Mailman import mm_cfg -from Mailman import Utils from Mailman import MailList +from Mailman import Utils +from Mailman import Version +from Mailman.configuration import config from Mailman.i18n import _ __i18n_templates__ = True @@ -36,7 +37,7 @@ __i18n_templates__ = True def parseargs(): - parser = optparse.OptionParser(version=mm_cfg.MAILMAN_VERSION, + parser = optparse.OptionParser(version=Version.MAILMAN_VERSION, usage=_("""\ %prog [options] [listname ...] @@ -47,6 +48,8 @@ Re-generate the Pipermail gzip'd archive flat files.""")) parser.add_option('-z', '--level', default=6, type='int', help=_('Specifies the compression level')) + parser.add_option('-C', '--config', + help=_('Alternative configuration file to use')) opts, args = parser.parse_args() if opts.level < 1 or opts.level > 9: parser.print_help() @@ -73,15 +76,16 @@ def compress(txtfile, opts): def main(): - if mm_cfg.ARCHIVE_TO_MBOX not in (1, 2) or mm_cfg.GZIP_ARCHIVE_TXT_FILES: + opts, args, parser = parseargs() + config.load(opts.config) + + if config.ARCHIVE_TO_MBOX not in (1, 2) or config.GZIP_ARCHIVE_TXT_FILES: # We're only going to run the nightly archiver if messages are # archived to the mbox, and the gzip file is not created on demand # (i.e. for every individual post). This is the normal mode of # operation. return - opts, args, parser = parseargs() - # Process all the specified lists for listname in set(args or Utils.list_names()): mlist = MailList.MailList(listname, lock=False) diff --git a/Mailman/bin/senddigests.py b/Mailman/bin/senddigests.py index fa01d3666..febaf4162 100644 --- a/Mailman/bin/senddigests.py +++ b/Mailman/bin/senddigests.py @@ -20,7 +20,8 @@ import optparse from Mailman import MailList from Mailman import Utils -from Mailman import mm_cfg +from Mailman import Version +from Mailman.configuration import config from Mailman.i18n import _ # Work around known problems with some RedHat cron daemons @@ -32,7 +33,7 @@ __i18n_templates__ = True def parseargs(): - parser = optparse.OptionParser(version=mm_cfg.MAILMAN_VERSION, + parser = optparse.OptionParser(version=Version.MAILMAN_VERSION, usage=_("""\ %prog [options] @@ -43,6 +44,8 @@ set.""")) dest='listnames', help=_("""\ Send the digest for the given list only, otherwise the digests for all lists are sent out. Multiple -l options may be given.""")) + parser.add_option('-C', '--config', + help=_('Alternative configuration file to use')) opts, args = parser.parse_args() if args: parser.print_help() @@ -54,6 +57,7 @@ lists are sent out. Multiple -l options may be given.""")) def main(): opts, args, parser = parseargs() + config.load(opts.config) for listname in set(opts.listnames or Utils.list_names()): mlist = MailList.MailList(listname, lock=False) diff --git a/Mailman/bin/show_qfiles.py b/Mailman/bin/show_qfiles.py index f49190b1d..449b265b4 100644 --- a/Mailman/bin/show_qfiles.py +++ b/Mailman/bin/show_qfiles.py @@ -19,7 +19,8 @@ import sys import optparse from cPickle import load -from Mailman import mm_cfg +from Mailman import Version +from Mailman.configuration import config from Mailman.i18n import _ __i18_templates__ = True @@ -27,7 +28,7 @@ __i18_templates__ = True def parseargs(): - parser = optparse.OptionParser(version=mm_cfg.MAILMAN_VERSION, + parser = optparse.OptionParser(version=Version.MAILMAN_VERSION, usage=_("""\ %%prog [options] qfiles ... @@ -35,6 +36,8 @@ Show the contents of one or more Mailman queue files.""")) parser.add_option('-q', '--quiet', default=False, action='store_true', help=_("Don't print 'helpful' message delimiters.")) + parser.add_option('-C', '--config', + help=_('Alternative configuration file to use')) opts, args = parser.parse_args() return parser, opts, args @@ -42,6 +45,7 @@ Show the contents of one or more Mailman queue files.""")) def main(): parser, opts, args = parseargs() + config.load(opts.config) for filename in args: if not opts.quiet: diff --git a/Mailman/configuration.py b/Mailman/configuration.py index 66aa6c191..ebc42c218 100644 --- a/Mailman/configuration.py +++ b/Mailman/configuration.py @@ -1,143 +1,144 @@ -# 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. - -"""Configuration file loading and management.""" - -import os -import errno - -from Mailman import Defaults -from Mailman import Errors - -_missing = object() - - - -class Configuration(object): - def __init__(self): - self.domains = {} # email host -> web host - self._reverse = None - - def load(self, filename=None): - # Load the configuration from the named file, or if not given, search - # in VAR_PREFIX for an etc/mailman.cfg file. If that file is missing, - # use Mailman/mm_cfg.py for backward compatibility. - # - # Whatever you find, create a namespace and execfile that file in it. - # The values in that namespace are exposed as attributes on this - # Configuration instance. - if filename is None: - filename = os.path.join(Defaults.VAR_PREFIX, 'etc', 'mailman.cfg') - # Set up the execfile namespace - ns = Defaults.__dict__.copy() - # Prune a few things, add a few things - del ns['__file__'] - del ns['__name__'] - del ns['__doc__'] - ns['add_domain'] = self.add_domain - # Attempt our first choice - path = os.path.abspath(os.path.expanduser(filename)) - try: - execfile(path, ns, ns) - except EnvironmentError, e: - if e.errno <> errno.ENOENT: - raise - # The file didn't exist, so try mm_cfg.py - from Mailman import mm_cfg - ns.update(mm_cfg.__dict__) - # Pull out the defaults - PREFIX = ns['PREFIX'] - VAR_PREFIX = ns['VAR_PREFIX'] - EXEC_PREFIX = ns['EXEC_PREFIX'] - # Now that we've loaded all the configuration files we're going to - # load, set up some useful directories. - self.LIST_DATA_DIR = os.path.join(VAR_PREFIX, 'lists') - self.LOG_DIR = os.path.join(VAR_PREFIX, 'logs') - self.LOCK_DIR = lockdir = os.path.join(VAR_PREFIX, 'locks') - self.DATA_DIR = datadir = os.path.join(VAR_PREFIX, 'data') - self.ETC_DIR = etcdir = os.path.join(VAR_PREFIX, 'etc') - self.SPAM_DIR = os.path.join(VAR_PREFIX, 'spam') - self.WRAPPER_DIR = os.path.join(EXEC_PREFIX, 'mail') - self.BIN_DIR = os.path.join(PREFIX, 'bin') - self.SCRIPTS_DIR = os.path.join(PREFIX, 'scripts') - self.TEMPLATE_DIR = os.path.join(PREFIX, 'templates') - self.MESSAGES_DIR = os.path.join(PREFIX, 'messages') - self.PUBLIC_ARCHIVE_FILE_DIR = os.path.join(VAR_PREFIX, - 'archives', 'public') - self.PRIVATE_ARCHIVE_FILE_DIR = os.path.join(VAR_PREFIX, - 'archives', 'private') - # Directories used by the qrunner subsystem - self.QUEUE_DIR = qdir = os.path.join(VAR_PREFIX, 'qfiles') - self.INQUEUE_DIR = os.path.join(qdir, 'in') - self.OUTQUEUE_DIR = os.path.join(qdir, 'out') - self.CMDQUEUE_DIR = os.path.join(qdir, 'commands') - self.BOUNCEQUEUE_DIR = os.path.join(qdir, 'bounces') - self.NEWSQUEUE_DIR = os.path.join(qdir, 'news') - self.ARCHQUEUE_DIR = os.path.join(qdir, 'archive') - self.SHUNTQUEUE_DIR = os.path.join(qdir, 'shunt') - self.VIRGINQUEUE_DIR = os.path.join(qdir, 'virgin') - self.BADQUEUE_DIR = os.path.join(qdir, 'bad') - self.RETRYQUEUE_DIR = os.path.join(qdir, 'retry') - self.MAILDIR_DIR = os.path.join(qdir, 'maildir') - # Other useful files - self.PIDFILE = os.path.join(datadir, - 'master-qrunner.pid') - self.SITE_PW_FILE = os.path.join(datadir, 'adm.pw') - self.LISTCREATOR_PW_FILE = os.path.join(datadir, 'creator.pw') - self.CONFIG_FILE = os.path.join(etcdir, 'mailman.cfg') - self.LOCK_FILE = os.path.join(lockdir, 'master-qrunner') - # Now update our dict so attribute syntax just works - if 'add_domain' in ns: - del ns['add_domain'] - self.__dict__.update(ns) - # Add the default domain if there are no virtual domains currently - # defined. - if not self.domains: - self.add_domain(self.DEFAULT_EMAIL_HOST, self.DEFAULT_URL_HOST) - - def add_domain(self, email_host, url_host): - """Add the definition of a virtual domain. - - email_host is the right-hand side of the posting email address, - e.g. 'example.com' in 'mylist@example.com'. url_host is the host name - part of the exposed web pages, e.g. 'www.example.com'.""" - if email_host in self.domains: - raise Errors.BadDomainSpecificationError( - 'Duplicate email host: %s' % email_host) - # Make sure there's only one mapping for the url_host - if url_host in self.domains.values(): - raise Errors.BadDomainSpecificationError( - 'Duplicate url host: %s' % url_host) - # We'll do the reverse mappings on-demand. There shouldn't be too - # many virtual hosts that it will really matter that much. - self.domains[email_host] = url_host - # Invalidate the reverse mapping cache - self._reverse = None - - # Given an email host name, the url host name can be looked up directly. - # This does the reverse mapping. - def get_email_host(self, url_host, default=None): - if self._reverse is None: - # XXX Can't use a generator comprehension until Python 2.4 is - # minimum requirement. - self._reverse = dict([(v, k) for k, v in self.domains.items()]) - return self._reverse.get(url_host, default) - - - -config = Configuration() - +# 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.
+
+"""Configuration file loading and management."""
+
+import os
+import errno
+
+from Mailman import Defaults
+from Mailman import Errors
+
+_missing = object()
+
+
+
+class Configuration(object):
+ def __init__(self):
+ self.domains = {} # email host -> web host
+ self._reverse = None
+
+ def load(self, filename=None):
+ # Load the configuration from the named file, or if not given, search
+ # in VAR_PREFIX for an etc/mailman.cfg file. If that file is missing,
+ # use Mailman/mm_cfg.py for backward compatibility.
+ #
+ # Whatever you find, create a namespace and execfile that file in it.
+ # The values in that namespace are exposed as attributes on this
+ # Configuration instance.
+ original_filename = filename
+ if filename is None:
+ filename = os.path.join(Defaults.VAR_PREFIX, 'etc', 'mailman.cfg')
+ # Set up the execfile namespace
+ ns = Defaults.__dict__.copy()
+ # Prune a few things, add a few things
+ del ns['__file__']
+ del ns['__name__']
+ del ns['__doc__']
+ ns['add_domain'] = self.add_domain
+ # Attempt our first choice
+ path = os.path.abspath(os.path.expanduser(filename))
+ try:
+ execfile(path, ns, ns)
+ except EnvironmentError, e:
+ if e.errno <> errno.ENOENT or original_filename:
+ raise
+ # The file didn't exist, so try mm_cfg.py
+ from Mailman import mm_cfg
+ ns.update(mm_cfg.__dict__)
+ # Pull out the defaults
+ PREFIX = ns['PREFIX']
+ VAR_PREFIX = ns['VAR_PREFIX']
+ EXEC_PREFIX = ns['EXEC_PREFIX']
+ # Now that we've loaded all the configuration files we're going to
+ # load, set up some useful directories.
+ self.LIST_DATA_DIR = os.path.join(VAR_PREFIX, 'lists')
+ self.LOG_DIR = os.path.join(VAR_PREFIX, 'logs')
+ self.LOCK_DIR = lockdir = os.path.join(VAR_PREFIX, 'locks')
+ self.DATA_DIR = datadir = os.path.join(VAR_PREFIX, 'data')
+ self.ETC_DIR = etcdir = os.path.join(VAR_PREFIX, 'etc')
+ self.SPAM_DIR = os.path.join(VAR_PREFIX, 'spam')
+ self.WRAPPER_DIR = os.path.join(EXEC_PREFIX, 'mail')
+ self.BIN_DIR = os.path.join(PREFIX, 'bin')
+ self.SCRIPTS_DIR = os.path.join(PREFIX, 'scripts')
+ self.TEMPLATE_DIR = os.path.join(PREFIX, 'templates')
+ self.MESSAGES_DIR = os.path.join(PREFIX, 'messages')
+ self.PUBLIC_ARCHIVE_FILE_DIR = os.path.join(VAR_PREFIX,
+ 'archives', 'public')
+ self.PRIVATE_ARCHIVE_FILE_DIR = os.path.join(VAR_PREFIX,
+ 'archives', 'private')
+ # Directories used by the qrunner subsystem
+ self.QUEUE_DIR = qdir = os.path.join(VAR_PREFIX, 'qfiles')
+ self.INQUEUE_DIR = os.path.join(qdir, 'in')
+ self.OUTQUEUE_DIR = os.path.join(qdir, 'out')
+ self.CMDQUEUE_DIR = os.path.join(qdir, 'commands')
+ self.BOUNCEQUEUE_DIR = os.path.join(qdir, 'bounces')
+ self.NEWSQUEUE_DIR = os.path.join(qdir, 'news')
+ self.ARCHQUEUE_DIR = os.path.join(qdir, 'archive')
+ self.SHUNTQUEUE_DIR = os.path.join(qdir, 'shunt')
+ self.VIRGINQUEUE_DIR = os.path.join(qdir, 'virgin')
+ self.BADQUEUE_DIR = os.path.join(qdir, 'bad')
+ self.RETRYQUEUE_DIR = os.path.join(qdir, 'retry')
+ self.MAILDIR_DIR = os.path.join(qdir, 'maildir')
+ # Other useful files
+ self.PIDFILE = os.path.join(datadir,
+ 'master-qrunner.pid')
+ self.SITE_PW_FILE = os.path.join(datadir, 'adm.pw')
+ self.LISTCREATOR_PW_FILE = os.path.join(datadir, 'creator.pw')
+ self.CONFIG_FILE = os.path.join(etcdir, 'mailman.cfg')
+ self.LOCK_FILE = os.path.join(lockdir, 'master-qrunner')
+ # Now update our dict so attribute syntax just works
+ if 'add_domain' in ns:
+ del ns['add_domain']
+ self.__dict__.update(ns)
+ # Add the default domain if there are no virtual domains currently
+ # defined.
+ if not self.domains:
+ self.add_domain(self.DEFAULT_EMAIL_HOST, self.DEFAULT_URL_HOST)
+
+ def add_domain(self, email_host, url_host):
+ """Add the definition of a virtual domain.
+
+ email_host is the right-hand side of the posting email address,
+ e.g. 'example.com' in 'mylist@example.com'. url_host is the host name
+ part of the exposed web pages, e.g. 'www.example.com'."""
+ if email_host in self.domains:
+ raise Errors.BadDomainSpecificationError(
+ 'Duplicate email host: %s' % email_host)
+ # Make sure there's only one mapping for the url_host
+ if url_host in self.domains.values():
+ raise Errors.BadDomainSpecificationError(
+ 'Duplicate url host: %s' % url_host)
+ # We'll do the reverse mappings on-demand. There shouldn't be too
+ # many virtual hosts that it will really matter that much.
+ self.domains[email_host] = url_host
+ # Invalidate the reverse mapping cache
+ self._reverse = None
+
+ # Given an email host name, the url host name can be looked up directly.
+ # This does the reverse mapping.
+ def get_email_host(self, url_host, default=None):
+ if self._reverse is None:
+ # XXX Can't use a generator comprehension until Python 2.4 is
+ # minimum requirement.
+ self._reverse = dict([(v, k) for k, v in self.domains.items()])
+ return self._reverse.get(url_host, default)
+
+
+
+config = Configuration()
+
diff --git a/Mailman/loginit.py b/Mailman/loginit.py index 2dfa00837..85762e7ec 100644 --- a/Mailman/loginit.py +++ b/Mailman/loginit.py @@ -1,130 +1,132 @@ -# 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. - -"""Logging initialization, using Python's standard logging package. - -This module cannot be called 'logging' because that would interfere with the -import below. Ah, for Python 2.5 and absolute imports. -""" - -import os -import codecs -import logging - -from Mailman.configuration import config - -FMT = '%(asctime)s (%(process)d) %(message)s' -DATEFMT = '%b %d %H:%M:%S %Y' -LOGGERS = ( - 'bounce', - 'config', - 'debug', - 'error', - 'http', - 'locks', - 'mischief', - 'post', - 'qrunner', - 'smtp', - 'smtp-failure', - 'subscribe', - 'vette', - ) - -_handlers = [] - - - -class ReopenableFileHandler(logging.Handler): - def __init__(self, filename): - self._filename = filename - self._stream = self._open() - logging.Handler.__init__(self) - - def _open(self): - return codecs.open(self._filename, 'a', 'utf-8') - - def flush(self): - self._stream.flush() - - def emit(self, record): - try: - msg = self.format(record) - fs = '%s\n' - try: - self._stream.write(fs % msg) - except UnicodeError: - self._stream.write(fs % msg.encode('string-escape')) - self.flush() - except: - self.handleError(record) - - def close(self): - self.flush() - self._stream.close() - logging.Handler.close(self) - - def reopen(self): - self._stream.close() - self._stream = self._open() - - - -def initialize(propagate=False): - # XXX Don't call logging.basicConfig() because in Python 2.3, it adds a - # handler to the root logger that we don't want. When Python 2.4 is the - # minimum requirement, we can use basicConfig() with keyword arguments. - # - # The current set of Mailman logs are: - # - # error - All exceptions go to this log - # bounce - All bounce processing logs go here - # mischief - Various types of hostile activity - # post - Information about messages posted to mailing lists - # vette - Information related to admindb activity - # smtp - Successful SMTP activity - # smtp-failure - Unsuccessful SMTP activity - # subscribe - Information about leaves/joins - # config - Configuration issues - # locks - Lock steals - # qrunner - qrunner start/stops - # - # There was also a 'debug' logger, but that was mostly unused, so instead - # we'll use debug level on existing loggers. - # - # Start by creating a common formatter and the root logger. - formatter = logging.Formatter(fmt=FMT, datefmt=DATEFMT) - log = logging.getLogger('mailman') - handler = logging.StreamHandler() - handler.setFormatter(formatter) - log.addHandler(handler) - log.setLevel(logging.INFO) - # Create the subloggers - for logger in LOGGERS: - log = logging.getLogger('mailman.' + logger) - # Propagation to the root logger is how we handle logging to stderr - # when the qrunners are not run as a subprocess of mailmanctl. - log.propagate = propagate - handler = ReopenableFileHandler(os.path.join(config.LOG_DIR, logger)) - _handlers.append(handler) - handler.setFormatter(formatter) - log.addHandler(handler) - - - -def reopen(): - for handler in _handlers: - handler.reopen() +# 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.
+
+"""Logging initialization, using Python's standard logging package.
+
+This module cannot be called 'logging' because that would interfere with the
+import below. Ah, for Python 2.5 and absolute imports.
+"""
+
+import os
+import codecs
+import logging
+
+from Mailman.configuration import config
+
+FMT = '%(asctime)s (%(process)d) %(message)s'
+DATEFMT = '%b %d %H:%M:%S %Y'
+LOGGERS = (
+ 'bounce',
+ 'config',
+ 'debug',
+ 'error',
+ 'fromusenet',
+ 'http',
+ 'locks',
+ 'mischief',
+ 'post',
+ 'qrunner',
+ 'smtp',
+ 'smtp-failure',
+ 'subscribe',
+ 'vette',
+ )
+
+_handlers = []
+
+
+
+class ReopenableFileHandler(logging.Handler):
+ def __init__(self, filename):
+ self._filename = filename
+ self._stream = self._open()
+ logging.Handler.__init__(self)
+
+ def _open(self):
+ return codecs.open(self._filename, 'a', 'utf-8')
+
+ def flush(self):
+ self._stream.flush()
+
+ def emit(self, record):
+ try:
+ msg = self.format(record)
+ fs = '%s\n'
+ try:
+ self._stream.write(fs % msg)
+ except UnicodeError:
+ self._stream.write(fs % msg.encode('string-escape'))
+ self.flush()
+ except:
+ self.handleError(record)
+
+ def close(self):
+ self.flush()
+ self._stream.close()
+ logging.Handler.close(self)
+
+ def reopen(self):
+ self._stream.close()
+ self._stream = self._open()
+
+
+
+def initialize(propagate=False):
+ # XXX Don't call logging.basicConfig() because in Python 2.3, it adds a
+ # handler to the root logger that we don't want. When Python 2.4 is the
+ # minimum requirement, we can use basicConfig() with keyword arguments.
+ #
+ # The current set of Mailman logs are:
+ #
+ # error - All exceptions go to this log
+ # bounce - All bounce processing logs go here
+ # mischief - Various types of hostile activity
+ # post - Information about messages posted to mailing lists
+ # vette - Information related to admindb activity
+ # smtp - Successful SMTP activity
+ # smtp-failure - Unsuccessful SMTP activity
+ # subscribe - Information about leaves/joins
+ # config - Configuration issues
+ # locks - Lock steals
+ # qrunner - qrunner start/stops
+ # fromusenet - Information related to the Usenet to Mailman gateway
+ #
+ # There was also a 'debug' logger, but that was mostly unused, so instead
+ # we'll use debug level on existing loggers.
+ #
+ # Start by creating a common formatter and the root logger.
+ formatter = logging.Formatter(fmt=FMT, datefmt=DATEFMT)
+ log = logging.getLogger('mailman')
+ handler = logging.StreamHandler()
+ handler.setFormatter(formatter)
+ log.addHandler(handler)
+ log.setLevel(logging.INFO)
+ # Create the subloggers
+ for logger in LOGGERS:
+ log = logging.getLogger('mailman.' + logger)
+ # Propagation to the root logger is how we handle logging to stderr
+ # when the qrunners are not run as a subprocess of mailmanctl.
+ log.propagate = propagate
+ handler = ReopenableFileHandler(os.path.join(config.LOG_DIR, logger))
+ _handlers.append(handler)
+ handler.setFormatter(formatter)
+ log.addHandler(handler)
+
+
+
+def reopen():
+ for handler in _handlers:
+ handler.reopen()
|
