diff options
| author | bwarsaw | 2001-05-10 22:33:26 +0000 |
|---|---|---|
| committer | bwarsaw | 2001-05-10 22:33:26 +0000 |
| commit | 08eebcc9c4562bb2e9e7a9c879d6ba4c4ff3b719 (patch) | |
| tree | ecd5c3a549ee8ab625d586dd532d69c5ca046b6e /Mailman/MTA/Postfix.py | |
| parent | 49f4bdb57d94c2e5d2986bfebe4457601645a907 (diff) | |
| download | mailman-08eebcc9c4562bb2e9e7a9c879d6ba4c4ff3b719.tar.gz mailman-08eebcc9c4562bb2e9e7a9c879d6ba4c4ff3b719.tar.zst mailman-08eebcc9c4562bb2e9e7a9c879d6ba4c4ff3b719.zip | |
Diffstat (limited to 'Mailman/MTA/Postfix.py')
| -rw-r--r-- | Mailman/MTA/Postfix.py | 149 |
1 files changed, 120 insertions, 29 deletions
diff --git a/Mailman/MTA/Postfix.py b/Mailman/MTA/Postfix.py index 5a993d46d..7578435c5 100644 --- a/Mailman/MTA/Postfix.py +++ b/Mailman/MTA/Postfix.py @@ -25,59 +25,150 @@ import time import dbhash import errno import pwd -import grp from stat import * from Mailman import mm_cfg +from Mailman import LockFile from Mailman.i18n import _ +from Mailman.MTA.Utils import makealiases -DBFILE = os.path.join(mm_cfg.DATA_DIR, 'aliases.db') +TEXTFILE = os.path.join(mm_cfg.DATA_DIR, 'aliases') +DBFILE = TEXTFILE + '.db' +LOCKFILE = os.path.join(mm_cfg.LOCK_DIR, 'creator') -def _addlist(listname, db): - wrapper = os.path.join(mm_cfg.WRAPPER_DIR, 'wrapper') - # Every key and value in the dbhash file as created by Postfix must end in - # a null byte. That is, except YP_LAST_MODIFIED and YP_MASTER_NAME. - db[listname + '\0'] = '"|%s post %s"\0' % (wrapper, listname) - db[listname + '-admin\0'] = '"|%s mailowner %s"\0' % (wrapper, listname) - db[listname + '-owner\0'] = '%s-admin\0' % listname - db[listname + '-request\0'] = '"|%s mailcmd %s"\0' % (wrapper, listname) - # Always update YP_LAST_MODIFIED - db['YP_LAST_MODIFIED'] = '%010d' % time.time() - # Add a YP_MASTER_NAME only if there isn't one already - if not db.has_key('YP_MASTER_NAME'): - db['YP_MASTER_NAME'] = socket.getfqdn() +def makelock(): + return LockFile.LockFile(LOCKFILE) -def _rmlist(listname, db): - for extra in ('', '-admin', '-owner', '-request'): - try: - del db[listname + extra + '\0'] - except KeyError: - pass +def addlist(mlist, db, fp): + listname = mlist.internal_name() + fieldsz = len(listname) + len('-request') + # Seek to the end of the file, but if it's empty write the standard + # disclaimer. + fp.seek(0, 2) + if not fp.tell(): + print >> fp, """\ +# This file is generated by Mailman, and is kept in sync with the +# binary hash file aliases.db. YOU SHOULD NOT MANUALLY EDIT THIS FILE +# unless you know what you're doing, and can keep the two files properly +# in sync. If you screw it up, you're on your own. +""" + # The text file entries get a little extra info + print >> fp, '# STANZA START:', listname + print >> fp, '# CREATED:', time.ctime() + # Now add all the standard alias entries + for k, v in makealiases(listname): + # Every key and value in the dbhash file as created by Postfix + # must end in a null byte. That is, except YP_LAST_MODIFIED and + # YP_MASTER_NAME. + db[k + '\0'] = v + '\0' + # Format the text file nicely + print >> fp, k + ':', ((fieldsz - len(k)) * ' '), v # Always update YP_LAST_MODIFIED db['YP_LAST_MODIFIED'] = '%010d' % time.time() # Add a YP_MASTER_NAME only if there isn't one already if not db.has_key('YP_MASTER_NAME'): db['YP_MASTER_NAME'] = socket.getfqdn() + # Finish the text file stanza + print >> fp, '# STANZA END:', listname + print >> fp def create(mlist): - listname = mlist.internal_name() - db = dbhash.open(DBFILE, 'c') - _addlist(listname, db) - db.sync() + # Acquire the global list database lock + lock = makelock() + lock.lock() + try: + # Crack open the dbhash file + db = dbhash.open(DBFILE, 'c') + # Crack open the plain text file + try: + fp = open(TEXTFILE, 'r+') + except IOError, e: + if e.errno <> errno.ENOENT: raise + omask = os.umask(007) + try: + fp = open(TEXTFILE, 'w+') + finally: + os.umask(omask) + + addlist(mlist, db, fp) + # And flush everything out to disk + db.sync() + fp.close() + finally: + lock.unlock(unconditionally=1) def remove(mlist): - listname = mlist.internal_name() - db = dbhash.open(DBFILE, 'c') - _rmlist(listname, db) - db.sync() + # Acquire the global list database lock + lock = LockFile.LockFile(LOCKFILE) + lock.lock() + try: + listname = mlist.internal_name() + # Crack open the dbhash file, and delete all the entries + db = dbhash.open(DBFILE, 'c') + for k, v in makealiases(listname): + try: + del db[k + '\0'] + except KeyError: + pass + # Always update YP_LAST_MODIFIED + db['YP_LAST_MODIFIED'] = '%010d' % time.time() + # Add a YP_MASTER_NAME only if there isn't one already + if not db.has_key('YP_MASTER_NAME'): + db['YP_MASTER_NAME'] = socket.getfqdn() + # And flush the changes to disk + db.sync() + # Now do our best to filter out the proper stanza from the text file. + # The text file better exist! + outfile = TEXTFILE + try: + infp = open(TEXTFILE) + except IOError, e: + if e.errno <> errno.ENOENT: raise + # Otherwise, there's no text file to filter so we're done. + return + omask = os.umask(007) + try: + outfp = open(TEXTFILE + '.tmp', 'w') + finally: + os.umask(omask) + filteroutp = 0 + start = '# STANZA START: ' + listname + end = '# STANZA END: ' + listname + while 1: + line = infp.readline() + if not line: + break + # If we're filtering out a stanza, just look for the end marker + # and filter out everything in between. If we're not in the + # middle of filter out a stanza, we're just looking for the proper + # begin marker. + if filteroutp: + if line.startswith(end): + filteroutp = 0 + # Discard the trailing blank line, but don't worry if + # we're at the end of the file. + infp.readline() + # Otherwise, ignore the line + else: + if line.startswith(start): + # Filter out this stanza + filteroutp = 1 + else: + outfp.write(line) + # Close up shop, and rotate the files + infp.close() + outfp.close() + os.rename(TEXTFILE+'.tmp', TEXTFILE) + finally: + lock.unlock(unconditionally=1) |
