1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
|
#!/usr/bin/python3
# vim:set fileencoding=utf-8 et ts=4 sts=4 sw=4:
# This file is shared between postinst and config
import configparser
import debconf
import os
import sys
PREFIX_SIZE=len('apt-listchannges')
DEFAULT_SEEN_DB='/var/lib/apt/listchanges.db'
SECTION='apt'
def _tmpl2Key(name):
return name[PREFIX_SIZE:].replace('-', '_')
def _debug(*args):
if 'APT_LISTCHANGES_DEBCONF_DEBUG' in os.environ:
print(*args, file=sys.stderr)
def _handleString(cfgkey, config, template, db, fromConfig):
_debug("handleString(", template, cfgkey, fromConfig, ")")
if fromConfig:
value = config.get(SECTION, cfgkey)
if value == 'none': value = ''
db.set(template, value)
else:
value = db.getString(template)
if value == '': value = 'none'
config.set(SECTION, cfgkey, value)
def _handleList(cfgkey, config, template, db, fromConfig):
_debug("handleList(", template, cfgkey, fromConfig, ")")
if fromConfig:
value = config.get(SECTION, cfgkey)
db.set(template, value.lower())
else:
value = db.getString(template)
config.set(SECTION, cfgkey, value)
def _handleBoolean(cfgkey, config, template, db, fromConfig):
value = config.getboolean(SECTION, cfgkey, fallback=None)
_debug("handleBoolean(", template, cfgkey, fromConfig, "), old config value:", value)
if fromConfig:
db.set(template, str(value).lower())
else:
newvalue = db.getBoolean(template)
if value == None or value != newvalue:
config.set(SECTION, cfgkey, str(newvalue).lower())
def _handleSeen(cfgkey, config, template, db, fromConfig):
# The 'save-seen' is very special: a path in config file,
# but in debconf is stored as boolean...
value = config.get(SECTION, cfgkey, fallback=None)
_debug("handleSeen(", template, cfgkey, fromConfig, "), old config value:", value)
if fromConfig:
db.set(template, str(value and value != 'none').lower())
elif not db.getBoolean(template):
value = 'none'
elif not value or value == 'none':
value = DEFAULT_SEEN_DB
config.set(SECTION, cfgkey, value)
IDX_QUESTION_NUMBER = 0
IDX_PRIORITY = 1
IDX_HANDLER = 2
IDX_SKIP = 3
IDX_CHECK = 4
def _checkFrontend(frontend):
if frontend == 'none':
return True
NAMES['apt-listchanges/confirm'][IDX_SKIP] = frontend == 'mail'
return False
def _checkWhich(which):
NAMES['apt-listchanges/no-network'][IDX_SKIP] = which == 'news'
return False
def _checkEmailAddress(emailAddress):
NAMES['apt-listchanges/email-format'][IDX_SKIP] = not emailAddress
return False
NAMES = {'apt-listchanges/frontend' : [1, debconf.MEDIUM, _handleList, False, _checkFrontend],
'apt-listchanges/which' : [2, debconf.MEDIUM, _handleList, False, _checkWhich],
'apt-listchanges/no-network' : [3, debconf.HIGH, _handleBoolean, False, None],
'apt-listchanges/email-address': [4, debconf.LOW, _handleString, False, _checkEmailAddress],
'apt-listchanges/email-format' : [5, debconf.LOW, _handleList, False, None],
'apt-listchanges/confirm' : [6, debconf.LOW, _handleBoolean, False, None],
'apt-listchanges/headers' : [7, debconf.LOW, _handleBoolean, False, None],
'apt-listchanges/reverse' : [8, debconf.LOW, _handleBoolean, False, None],
'apt-listchanges/save-seen' : [9, debconf.LOW, _handleSeen, False, None]
}
def _updateDebconfFromConfig(config, db):
_debug("updateDebconfFromConfig()")
for tmpl, params in NAMES.items(): # don't need to be sorted
cfgkey = _tmpl2Key(tmpl)
if config.has_option(SECTION, cfgkey):
params[IDX_HANDLER](cfgkey, config, tmpl, db, True)
db.fset(tmpl, 'seen', 'true')
def _communicateWithDebconf(config, db, is_postinst):
_debug("communicateWithDebconf(", is_postinst, ")")
for tmpl, params in sorted(NAMES.items(), key = lambda x : x[1][IDX_QUESTION_NUMBER]):
if params[IDX_SKIP]:
_debug("skipping %s" % tmpl)
continue
if is_postinst: # store the value
params[IDX_HANDLER](_tmpl2Key(tmpl), config, tmpl, db, False)
else: # ask for the value
db.forceInput(params[IDX_PRIORITY], tmpl)
if params[IDX_CHECK]:
db.go()
if params[IDX_CHECK]:
value = db.get(tmpl)
if params[IDX_CHECK](value):
_debug("finishing on %s" % tmpl)
return
if not is_postinst:
db.go()
def main(argv):
if len(argv) < 3:
print("Usage: script postinst|config config_file mainscript_params",
file=sys.stderr)
sys.exit(1)
debconf.runFrontEnd()
is_postinst = argv[1] == 'postinst' # otherwise it is config
config_file = argv[2]
_debug("apt-listchanges debconf script started(", is_postinst, config_file, ")")
config = configparser.ConfigParser()
config.read(config_file)
if not config.has_section(SECTION):
config.add_section(SECTION)
try:
output = os.fdopen(3, "wt")
except Exception as ex:
_debug("failed to open file descriptor 3", str(ex))
output = sys.stdout
db = debconf.Debconf(write=output)
if not is_postinst:
_updateDebconfFromConfig(config, db)
_communicateWithDebconf(config, db, is_postinst)
if is_postinst:
with open(config_file + '.new', 'wt') as newfile:
config.write(newfile, space_around_delimiters=False)
os.fchmod(newfile.fileno(), 0o644)
if __name__ == "__main__":
main(sys.argv)
sys.exit(0)
|