1 |
#!/usr/bin/env python |
2 |
# DHCP Client Exit Hooks Installer |
3 |
# |
4 |
# Douglas Thrift |
5 |
# |
6 |
# $Id$ |
7 |
|
8 |
import optparse |
9 |
import os |
10 |
import re |
11 |
import sys |
12 |
import tempfile |
13 |
|
14 |
HOOKS = 'dhclient-exit-hooks' |
15 |
VARIABLES = { |
16 |
'tunnelbroker': { |
17 |
'pass': None, |
18 |
'user_id': None, |
19 |
'tunnel_id': None, |
20 |
}, |
21 |
'dns': { |
22 |
'key': None, |
23 |
'secret': None, |
24 |
}, |
25 |
} |
26 |
|
27 |
def parse(hooks, callback): |
28 |
functions = re.compile(r'^(%s)\(\)$' % '|'.join(VARIABLES.iterkeys())) |
29 |
function = None |
30 |
|
31 |
with open(hooks, 'rb') as hooks: |
32 |
for line in hooks: |
33 |
if line == '}\n': |
34 |
function = None |
35 |
else: |
36 |
match = functions.match(line) |
37 |
|
38 |
if match is not None: |
39 |
function = match.group(1) |
40 |
|
41 |
callback(line, function, VARIABLES.get(function)) |
42 |
|
43 |
if __name__ == '__main__': |
44 |
import readline |
45 |
|
46 |
parser = optparse.OptionParser(usage = '%prog [options] [DIRECTORY]') |
47 |
|
48 |
def variables(option, opt, value, parser, *args, **kwargs): |
49 |
variables = VARIABLES.get(value[0]) |
50 |
|
51 |
if variables is None: |
52 |
raise optparse.OptionValueError, '%s unknown function "%s"' % (opt, value[0]) |
53 |
|
54 |
if value[1] not in variables: |
55 |
raise optparse.OptionValueError, '%s unknown variable "%s"' % (opt, value[1]) |
56 |
|
57 |
parser.values.ensure_value(option.dest, set()).add(value) |
58 |
|
59 |
parser.add_option('-f', '--force', action = 'callback', type = 'string', dest = 'force', default = set(), nargs = 2, callback = variables, metavar = 'FUNCTION VARIABLE') |
60 |
|
61 |
options, args = parser.parse_args() |
62 |
|
63 |
if len(args) != 1: |
64 |
parser.error('no directory specified') |
65 |
|
66 |
os.umask(077) |
67 |
|
68 |
hooks = os.path.join(args[0], HOOKS) |
69 |
|
70 |
if os.path.exists(hooks): |
71 |
def read(line, function, variables): |
72 |
if function is not None: |
73 |
match = re.match(r"^\tlocal (%s)='(.*)'$" % '|'.join(variables.iterkeys()), line) |
74 |
|
75 |
if match is not None: |
76 |
variable, value = match.group(1, 2) |
77 |
|
78 |
if (function, variable) not in options.force: |
79 |
variables[variable] = value |
80 |
|
81 |
parse(hooks, read) |
82 |
|
83 |
with tempfile.NamedTemporaryFile('wb', prefix = HOOKS + '.', dir = args[0]) as temp: |
84 |
def write(line, function, variables): |
85 |
if function is not None: |
86 |
match = re.match(r'''^\t(?:read -p '{0} ({1}): ' -r \1|local ({1})=`python -c "(import .+); print (.*'{0} \2: '.*)"`)$'''.format(function, '|'.join(variables.iterkeys())), line) |
87 |
|
88 |
if match is not None: |
89 |
variable = match.group(1) |
90 |
|
91 |
if variable is None: |
92 |
variable, imports, python = match.group(2, 3, 4) |
93 |
else: |
94 |
imports, python = None, None |
95 |
|
96 |
value = variables[variable] |
97 |
|
98 |
if value is None: |
99 |
if python is not None: |
100 |
exec imports |
101 |
|
102 |
value = eval(python) |
103 |
else: |
104 |
value = raw_input('%s %s: ' % (function, variable)) |
105 |
|
106 |
line = "\tlocal %s='%s'\n" % (variable, value) |
107 |
|
108 |
temp.write(line) |
109 |
|
110 |
parse(HOOKS, write) |
111 |
|
112 |
temp.delete = False |
113 |
|
114 |
os.rename(temp.name, hooks) |