From 2c4212fa3665fa1467569301515bfdbdcd4a3311 Mon Sep 17 00:00:00 2001 From: Joshua Tauberer Date: Sun, 8 Jun 2014 17:23:06 -0400 Subject: [PATCH] use editconf.py to mangle /etc/postfix/master.cf * using it to enable the Postfix submission service * per @mkropat's suggestion in #69, set an option to distinguish submission from regular smpd in syslog by giving submission a new name (doing this here to test that editconf is working right on master.cf) --- setup/mail.sh | 8 +++- tools/editconf.py | 108 +++++++++++++++++++++++++++++++++------------- 2 files changed, 84 insertions(+), 32 deletions(-) diff --git a/setup/mail.sh b/setup/mail.sh index 2cfbc43b..1722a962 100755 --- a/setup/mail.sh +++ b/setup/mail.sh @@ -1,3 +1,4 @@ +#!/bin/bash # SMTP/IMAP: Postfix and Dovecot ################################ @@ -25,8 +26,11 @@ mkdir -p $STORAGE_ROOT/mail # POSTFIX ######### -# Enable the 'submission' port 587 listener. -sed -i "s/#submission/submission/" /etc/postfix/master.cf +# Enable the 'submission' port 587 smtpd server, and give it a different +# name in syslog to distinguish it from the port 25 smtpd server. +tools/editconf.py /etc/postfix/master.cf -s -w \ + "submission=inet n - - - - smtpd + -o syslog_name=postfix/submission" # Enable TLS and require it for all user authentication. tools/editconf.py /etc/postfix/main.cf \ diff --git a/tools/editconf.py b/tools/editconf.py index da7c25bf..47ca1b0a 100755 --- a/tools/editconf.py +++ b/tools/editconf.py @@ -1,10 +1,30 @@ #!/usr/bin/python3 +# +# This is a helper tool for editing configuration files during the setup +# process. The tool is given new values for settings as command-line +# arguments. It comments-out existing setting values in the configuration +# file and adds new values either after their former location or at the +# end. +# +# The configuration file has settings that look like: +# +# NAME=VALUE +# +# If the -s option is given, then space becomes the delimiter, i.e.: +# +# NAME VALUE +# +# If the -w option is given, then setting lines continue onto following +# lines while the lines start with whitespace, e.g.: +# +# NAME VAL +# UE import sys, re # sanity check if len(sys.argv) < 3: - print("usage: python3 editconf.py /etc/file.conf [-s] NAME=VAL [NAME=VAL ...]") + print("usage: python3 editconf.py /etc/file.conf [-s] [-w] [-t] NAME=VAL [NAME=VAL ...]") sys.exit(1) # parse command line arguments @@ -13,39 +33,64 @@ settings = sys.argv[2:] delimiter = "=" delimiter_re = r"\s*=\s*" -if settings[0] == "-s": - settings.pop(0) - delimiter = " " - delimiter_re = r"\s+" +folded_lines = False +testing = False +while settings[0][0] == "-" and settings[0] != "--": + opt = settings.pop(0) + if opt == "-s": + # Space is the delimiter + delimiter = " " + delimiter_re = r"\s+" + elif opt == "-w": + folded_lines = True + elif opt == "-t": + testing = True + else: + print("Invalid option.") + sys.exit(1) # create the new config file in memory + found = set() buf = "" -for line in open(filename): +input_lines = list(open(filename)) + +while len(input_lines) > 0: + line = input_lines.pop(0) + + # If this configuration file uses folded lines, append any folded lines + # into our input buffer. + if folded_lines and line[0] not in ("#", " ", ""): + while len(input_lines) > 0 and input_lines[0][0] in " \t": + line += input_lines.pop(0) + + # See if this line is for any settings passed on the command line. for i in range(len(settings)): + # Check that this line contain this setting from the command-line arguments. name, val = settings[i].split("=", 1) - m = re.match("\s*" + re.escape(name) + delimiter_re + "(.*?)\s*$", line) - if m: - # If this is already the setting, do nothing. - if m.group(1) == val: - buf += line - found.add(i) - break - - # comment-out the existing line - buf += "#" + line - - # if this option oddly appears more than once, don't add the setting again - if i in found: - break - - # add the new setting - buf += name + delimiter + val + "\n" - - # note that we've applied this option + m = re.match("\s*" + re.escape(name) + delimiter_re + "(.*?)\s*$", line, re.S) + if not m: continue + + # If this is already the setting, do nothing. + if m.group(1) == val: + buf += line found.add(i) - break + + # comment-out the existing line (also comment any folded lines) + buf += "#" + line.rstrip().replace("\n", "\n#") + "\n" + + # if this option oddly appears more than once, don't add the setting again + if i in found: + break + + # add the new setting + buf += name + delimiter + val + "\n" + + # note that we've applied this option + found.add(i) + + break else: # If did not match any setting names, pass this line through. buf += line @@ -56,7 +101,10 @@ for i in range(len(settings)): name, val = settings[i].split("=", 1) buf += name + delimiter + val + "\n" -# Write out the new file. -with open(filename, "w") as f: - f.write(buf) - +if not testing: + # Write out the new file. + with open(filename, "w") as f: + f.write(buf) +else: + # Just print the new file to stdout. + print(buf)