~ubuntu-branches/ubuntu/oneiric/openvpn/oneiric

« back to all changes in this revision

Viewing changes to win/wb.py

  • Committer: Bazaar Package Importer
  • Author(s): Chuck Short
  • Date: 2011-06-16 18:33:37 UTC
  • mfrom: (1.1.17 upstream) (10.2.13 sid)
  • Revision ID: james.westby@ubuntu.com-20110616183337-fv50u3kmiabewjq0
Tags: 2.2.0-2ubuntu1
* Merge from debian unstable.  Remaining changes:
 + debian/openvpn.init.d:
    - Do not use start-stop-daemon and </dev/null to avoid blocking boot.
    - Show per-VPN result messages.
    - Add "--script-security 2" by default for backwards compatabliity.
  + debian/control: Add lsb-base >= 3.2-14 to allow status_of_proc()
  + debian/update-resolv-conf: Support multiple domains.
  + fix bug where '--script-security 2' would be passed for all
    daemons after the first. (LP: #794916

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Python module containing general build functions
2
 
# for OpenVPN on Windows
3
 
 
4
 
import os, re, shutil, stat
5
 
 
6
 
autogen = "Automatically generated by OpenVPN Windows build system"
7
 
 
8
 
def get_config():
9
 
    kv = {}
10
 
    parse_version_m4(kv, home_fn('version.m4'))
11
 
    parse_settings_in(kv, mod_fn('settings.in'))
12
 
 
13
 
    # config fixups
14
 
    kv['DDKVER'] = os.path.basename(kv['DDK_PATH'])
15
 
    kv['DDKVER_MAJOR'] = re.match(r'^(\d+)\.', kv['DDKVER']).groups()[0]
16
 
 
17
 
    if 'VERSION_SUFFIX' in kv:
18
 
        kv['PRODUCT_VERSION'] += kv['VERSION_SUFFIX']
19
 
 
20
 
    return kv
21
 
 
22
 
def mod_fn(fn, src=__file__, real=True):
23
 
    p = os.path.join(os.path.dirname(src), os.path.normpath(fn))
24
 
    if real:
25
 
        p = os.path.realpath(p)
26
 
    return p
27
 
 
28
 
def home_fn(fn, real=True):
29
 
    return mod_fn(os.path.join('..', fn), real=real)
30
 
 
31
 
def cd_home():
32
 
    os.chdir(os.path.join(os.path.dirname(__file__), '..'))
33
 
 
34
 
def system(cmd):
35
 
    print "RUN:", cmd
36
 
    os.system(cmd)
37
 
 
38
 
def parse_version_m4(kv, version_m4):
39
 
    r = re.compile(r'^define\((\w+),\[(.*)\]\)$')
40
 
    f = open(version_m4)
41
 
    for line in f:
42
 
        line = line.rstrip()
43
 
        m = re.match(r, line)
44
 
        if m:
45
 
            g = m.groups()
46
 
            kv[g[0]] = g[1]
47
 
    f.close()
48
 
 
49
 
def parse_settings_in(kv, settings_in):
50
 
    r = re.compile(r'^!define\s+(\w+)(?:\s+"?(.*?)"?)?$')
51
 
    f = open(settings_in)
52
 
    for line in f:
53
 
        line = line.rstrip()
54
 
        m = re.match(r, line)
55
 
        if m:
56
 
            g = m.groups()
57
 
            kv[g[0]] = g[1] or ''
58
 
    f.close()
59
 
 
60
 
def dict_def(dict, newdefs):
61
 
    ret = dict.copy()
62
 
    ret.update(newdefs)
63
 
    return ret
64
 
 
65
 
def build_autodefs(kv, autodefs_in, autodefs_out):
66
 
    preprocess(kv,
67
 
               in_fn=autodefs_in,
68
 
               out_fn=autodefs_out,
69
 
               quote_begin='@',
70
 
               quote_end='@',
71
 
               head_comment='/* %s */\n\n' % autogen)
72
 
 
73
 
def preprocess(kv, in_fn, out_fn, quote_begin=None, quote_end=None, if_prefix=None, head_comment=None):
74
 
    def repfn(m):
75
 
        var, = m.groups()
76
 
        return kv.get(var, '')
77
 
 
78
 
    re_macro = re_ifdef = None
79
 
 
80
 
    if quote_begin and quote_end:
81
 
        re_macro = re.compile(r'%s(\w+)%s' % (re.escape(quote_begin), re.escape(quote_end)))
82
 
 
83
 
    if if_prefix:
84
 
        re_ifdef = re.compile(r'^\s*%sifdef\s+(\w+)\b' % (re.escape(if_prefix),))
85
 
        re_else = re.compile(r'^\s*%selse\b' % (re.escape(if_prefix),))
86
 
        re_endif = re.compile(r'^\s*%sendif\b' % (re.escape(if_prefix),))
87
 
 
88
 
    if_stack = []
89
 
    fin = open(in_fn)
90
 
    fout = open(out_fn, 'w')
91
 
    if head_comment:
92
 
        fout.write(head_comment)
93
 
    for line in fin:
94
 
        if re_ifdef:
95
 
            m = re.match(re_ifdef, line)
96
 
            if m:
97
 
                var, = m.groups()
98
 
                if_stack.append(int(var in kv))
99
 
                continue
100
 
            elif re.match(re_else, line):
101
 
                if_stack[-1] ^= 1
102
 
                continue
103
 
            elif re.match(re_endif, line):
104
 
                if_stack.pop()
105
 
                continue
106
 
        if not if_stack or min(if_stack):
107
 
            if re_macro:
108
 
                line = re.sub(re_macro, repfn, line)
109
 
            fout.write(line)
110
 
    assert not if_stack
111
 
    fin.close()
112
 
    fout.close()
113
 
 
114
 
def print_key_values(kv):
115
 
    for k, v in sorted(kv.items()):
116
 
        print "%s%s%s" % (k, ' '*(32-len(k)), repr(v))
117
 
 
118
 
def get_sources(makefile_am):
119
 
    c = set()
120
 
    h = set()
121
 
    f = open(makefile_am)
122
 
    state = False
123
 
    for line in f:
124
 
        line = line.rstrip()
125
 
        if line == 'openvpn_SOURCES = \\':
126
 
            state = True
127
 
        elif not line:
128
 
            state = False
129
 
        elif state:
130
 
            for sf in line.split():
131
 
                if sf.endswith('.c'):
132
 
                    c.add(sf[:-2])
133
 
                elif sf.endswith('.h'):
134
 
                    h.add(sf[:-2])
135
 
                elif sf == '\\':
136
 
                    pass
137
 
                else:
138
 
                    print >>sys.stderr, "Unrecognized filename:", sf
139
 
    f.close()
140
 
    return [ sorted(list(s)) for s in (c, h) ]
141
 
 
142
 
def output_mak_list(title, srclist, ext):
143
 
    ret = "%s =" % (title,)
144
 
    for x in srclist:
145
 
        ret += " \\\n\t%s.%s" % (x, ext)
146
 
    ret += '\n\n'
147
 
    return ret
148
 
 
149
 
def make_headers_objs(makefile_am):
150
 
    c, h = get_sources(makefile_am)
151
 
    ret = output_mak_list('HEADERS', h, 'h')
152
 
    ret += output_mak_list('OBJS', c, 'obj')
153
 
    return ret
154
 
 
155
 
def choose_arch(arch_name):
156
 
    if arch_name == 'x64':
157
 
        return (True,)
158
 
    elif arch_name == 'x86':
159
 
        return (False,)
160
 
    elif arch_name == 'all':
161
 
        return (True, False)
162
 
    else:
163
 
        raise ValueError("architecture ('%s') must be x86, x64, or all" % (arch_name,))
164
 
 
165
 
def rm_rf(dir):
166
 
    print "REMOVE", dir
167
 
    shutil.rmtree(dir, ignore_errors=True)
168
 
 
169
 
def mkdir(dir):
170
 
    print "MKDIR", dir
171
 
    os.mkdir(dir)
172
 
 
173
 
def cp_a(src, dest, dest_is_dir=True):
174
 
    if dest_is_dir:
175
 
        dest = os.path.join(dest, os.path.basename(src))
176
 
    print "COPY_DIR %s %s" % (src, dest)
177
 
    shutil.copytree(src, dest)
178
 
 
179
 
def cp(src, dest, dest_is_dir=True):
180
 
    if dest_is_dir:
181
 
        dest = os.path.join(dest, os.path.basename(src))
182
 
    print "COPY %s %s" % (src, dest)
183
 
    shutil.copyfile(src, dest)
184
 
 
185
 
def rm_rf(path):
186
 
    try:
187
 
        shutil.rmtree(path, onerror=onerror)
188
 
    except:
189
 
        pass
190
 
 
191
 
def onerror(func, path, exc_info):
192
 
    """
193
 
    Error handler for ``shutil.rmtree``.
194
 
 
195
 
    If the error is due to an access error (read only file)
196
 
    it attempts to add write permission and then retries.
197
 
 
198
 
    If the error is for another reason it re-raises the error.
199
 
 
200
 
    Usage : ``shutil.rmtree(path, onerror=onerror)``
201
 
    """
202
 
    if not os.access(path, os.W_OK):
203
 
        # Is the error an access error ?
204
 
        os.chmod(path, stat.S_IWUSR)
205
 
        func(path)
206
 
    else:
207
 
        raise
208
 
 
209
 
def mkdir_silent(dir):
210
 
    try:
211
 
        os.mkdir(dir)
212
 
    except:
213
 
        pass
214
 
 
215
 
config = get_config()
 
1
# Python module containing general build functions
 
2
# for OpenVPN on Windows
 
3
 
 
4
import os, re, shutil, stat
 
5
 
 
6
autogen = "Automatically generated by OpenVPN Windows build system"
 
7
 
 
8
def get_config():
 
9
    kv = {}
 
10
    parse_version_m4(kv, home_fn('version.m4'))
 
11
    parse_settings_in(kv, mod_fn('settings.in'))
 
12
 
 
13
    # config fixups
 
14
    kv['DDKVER'] = os.path.basename(kv['DDK_PATH'])
 
15
    kv['DDKVER_MAJOR'] = re.match(r'^(\d+)\.', kv['DDKVER']).groups()[0]
 
16
 
 
17
    if 'VERSION_SUFFIX' in kv:
 
18
        kv['PRODUCT_VERSION'] += kv['VERSION_SUFFIX']
 
19
 
 
20
    return kv
 
21
 
 
22
def get_build_params():
 
23
    kv = {}
 
24
    parse_build_params(kv,mod_fn('settings.in'))
 
25
 
 
26
    return kv
 
27
 
 
28
def mod_fn(fn, src=__file__, real=True):
 
29
    p = os.path.join(os.path.dirname(src), os.path.normpath(fn))
 
30
    if real:
 
31
        p = os.path.realpath(p)
 
32
    return p
 
33
 
 
34
def home_fn(fn, real=True):
 
35
    return mod_fn(os.path.join('..', fn), real=real)
 
36
 
 
37
def cd_home():
 
38
    os.chdir(os.path.join(os.path.dirname(__file__), '..'))
 
39
 
 
40
def cd_service_win32():
 
41
    os.chdir(os.path.join(os.path.dirname(__file__), '../service-win32'))
 
42
 
 
43
def system(cmd):
 
44
    print "RUN:", cmd
 
45
    os.system(cmd)
 
46
 
 
47
def run_in_vs_shell(cmd):
 
48
    """Make sure environment variables are setup before running command"""
 
49
    os.environ['PATH'] += ";%s\\VC" % (os.path.normpath(config['MSVC']),)
 
50
    system('cmd /c "vcvarsall.bat x86 && %s"' % (cmd,))
 
51
 
 
52
def parse_version_m4(kv, version_m4):
 
53
    '''Parse define lines in version.m4'''
 
54
    r = re.compile(r'^define\((\w+),\[(.*)\]\)$')
 
55
    f = open(version_m4)
 
56
    for line in f:
 
57
        line = line.rstrip()
 
58
        m = re.match(r, line)
 
59
 
 
60
        if m:
 
61
            g = m.groups()
 
62
 
 
63
            # If we encounter PRODUCT_TAP_WIN32_MIN_MAJOR or
 
64
            # PRODUCT_TAP_WIN32_MIN_MAJOR then we need to generate extra
 
65
            # variables, PRODUCT_TAP_MAJOR_VER and PRODUCT_TAP_MINOR_VER with 
 
66
            # the same contents. This is necessary because tap-win32/tapdrv.c 
 
67
            # build depends on those.
 
68
            if g[0] == 'PRODUCT_TAP_WIN32_MIN_MAJOR':
 
69
                kv['PRODUCT_TAP_MAJOR_VER'] = g[1]
 
70
            elif g[0] == 'PRODUCT_TAP_WIN32_MIN_MINOR':
 
71
                kv['PRODUCT_TAP_MINOR_VER'] = g[1]
 
72
 
 
73
            # Add the variable to build configuration
 
74
            kv[g[0]] = g[1]
 
75
    f.close()
 
76
 
 
77
def parse_settings_in(kv, settings_in):
 
78
    r = re.compile(r'^!define\s+(\w+)(?:\s+"?(.*?)"?)?$')
 
79
    f = open(settings_in)
 
80
    for line in f:
 
81
        line = line.rstrip()
 
82
        m = re.match(r, line)
 
83
        if m:
 
84
            g = m.groups()
 
85
            kv[g[0]] = g[1] or ''
 
86
    f.close()
 
87
 
 
88
def parse_build_params(kv, settings_in):
 
89
    r = re.compile(r'^!define\s+(ENABLE_\w+)\s+(\w+)')
 
90
 
 
91
    f = open(settings_in)
 
92
 
 
93
    for line in f:
 
94
        line = line.rstrip()
 
95
 
 
96
        # Check if this is a #define line starts with ENABLE_
 
97
        m = re.match(r, line)
 
98
 
 
99
        if m:
 
100
                g = m.groups()
 
101
                kv[g[0]] = g[1] or ''
 
102
    f.close()
 
103
 
 
104
def dict_def(dict, newdefs):
 
105
    ret = dict.copy()
 
106
    ret.update(newdefs)
 
107
    return ret
 
108
 
 
109
def build_autodefs(kv, autodefs_in, autodefs_out):
 
110
    preprocess(kv,
 
111
               in_fn=autodefs_in,
 
112
               out_fn=autodefs_out,
 
113
               quote_begin='@',
 
114
               quote_end='@',
 
115
               head_comment='/* %s */\n\n' % autogen)
 
116
 
 
117
def build_config_h(kv):
 
118
    """Generate static win/config.h to config.h to mimic autotools behavior"""
 
119
    preprocess(kv,
 
120
               in_fn=mod_fn('config.h.in'),
 
121
               out_fn=home_fn('config.h'),
 
122
               quote_begin='@',
 
123
               quote_end='@',
 
124
               head_comment='/* %s */\n\n' % autogen)
 
125
 
 
126
def build_configure_h(kv, configure_h_out, head_comment):
 
127
    """Generate a configure.h dynamically"""
 
128
    fout = open(configure_h_out, 'w')
 
129
 
 
130
    # These two variables are required to view build parameters during runtime 
 
131
    configure_defines='#define CONFIGURE_DEFINES \"'
 
132
    configure_call='#define CONFIGURE_CALL \" config_all.py \"'
 
133
 
 
134
    # Initialize the list of enabled features
 
135
    features = ''
 
136
 
 
137
    # Write the header
 
138
    fout.write(head_comment)
 
139
 
 
140
    dict = get_build_params()
 
141
 
 
142
    for key, value in dict.iteritems():
 
143
        # Add enabled features
 
144
        features = features + "#define " + key + " " + value + "\n"
 
145
 
 
146
        # Add each enabled feature to CONFIGURE_DEFINES list
 
147
        configure_defines = configure_defines + " " + key + "=" + value + ","
 
148
 
 
149
    configure_defines = configure_defines + "\"" + "\n"
 
150
 
 
151
    fout.write(features)
 
152
    fout.write(configure_defines)
 
153
    fout.write(configure_call)
 
154
 
 
155
 
 
156
    fout.close()
 
157
 
 
158
def build_version_m4_vars(version_m4_vars_out, head_comment):
 
159
    """Generate a temporary file containing variables from version.m4 in 
 
160
win/settings.in format. This done to allow importing them in win/openvpn.nsi"""
 
161
 
 
162
    fout = open(version_m4_vars_out, 'w')
 
163
    fout.write(head_comment)
 
164
 
 
165
    kv = {}
 
166
    parse_version_m4(kv, home_fn('version.m4'))
 
167
 
 
168
    for key, value in kv.iteritems():
 
169
         line = "!define " + key + "\t" + "\"" + value + "\"" + "\n"
 
170
         fout.write(line)
 
171
 
 
172
    fout.close()
 
173
 
 
174
def preprocess(kv, in_fn, out_fn, quote_begin=None, quote_end=None, if_prefix=None, head_comment=None):
 
175
    def repfn(m):
 
176
        var, = m.groups()
 
177
        return kv.get(var, '')
 
178
 
 
179
    re_macro = re_ifdef = None
 
180
 
 
181
    if quote_begin and quote_end:
 
182
        re_macro = re.compile(r'%s(\w+)%s' % (re.escape(quote_begin), re.escape(quote_end)))
 
183
 
 
184
    if if_prefix:
 
185
        re_ifdef = re.compile(r'^\s*%sifdef\s+(\w+)\b' % (re.escape(if_prefix),))
 
186
        re_else = re.compile(r'^\s*%selse\b' % (re.escape(if_prefix),))
 
187
        re_endif = re.compile(r'^\s*%sendif\b' % (re.escape(if_prefix),))
 
188
 
 
189
    if_stack = []
 
190
    fin = open(in_fn)
 
191
    fout = open(out_fn, 'w')
 
192
    if head_comment:
 
193
        fout.write(head_comment)
 
194
    for line in fin:
 
195
        if re_ifdef:
 
196
            m = re.match(re_ifdef, line)
 
197
            if m:
 
198
                var, = m.groups()
 
199
                if_stack.append(int(var in kv))
 
200
                continue
 
201
            elif re.match(re_else, line):
 
202
                if_stack[-1] ^= 1
 
203
                continue
 
204
            elif re.match(re_endif, line):
 
205
                if_stack.pop()
 
206
                continue
 
207
        if not if_stack or min(if_stack):
 
208
            if re_macro:
 
209
                line = re.sub(re_macro, repfn, line)
 
210
            fout.write(line)
 
211
    assert not if_stack
 
212
    fin.close()
 
213
    fout.close()
 
214
 
 
215
def print_key_values(kv):
 
216
    for k, v in sorted(kv.items()):
 
217
        print "%s%s%s" % (k, ' '*(32-len(k)), repr(v))
 
218
 
 
219
def get_sources(makefile_am):
 
220
    """Parse ../Makefile.am to obtain a list of .h and .c files"""
 
221
    c = set()
 
222
    h = set()
 
223
    f = open(makefile_am)
 
224
    state = False
 
225
    for line in f:
 
226
        line = line.rstrip()
 
227
        if line == 'openvpn_SOURCES = \\':
 
228
            state = True
 
229
        elif not line:
 
230
            state = False
 
231
        elif state:
 
232
            for sf in line.split():
 
233
                if sf.endswith('.c'):
 
234
                    c.add(sf[:-2])
 
235
                elif sf.endswith('.h'):
 
236
                    h.add(sf[:-2])
 
237
                elif sf == '\\':
 
238
                    pass
 
239
                else:
 
240
                    print >>sys.stderr, "Unrecognized filename:", sf
 
241
    f.close()
 
242
    return [ sorted(list(s)) for s in (c, h) ]
 
243
 
 
244
def output_mak_list(title, srclist, ext):
 
245
    ret = "%s =" % (title,)
 
246
    for x in srclist:
 
247
        ret += " \\\n\t%s.%s" % (x, ext)
 
248
    ret += '\n\n'
 
249
    return ret
 
250
 
 
251
def make_headers_objs(makefile_am):
 
252
    """Generate HEADER and OBJS entries dynamically from ../Makefile.am"""
 
253
    c, h = get_sources(makefile_am)
 
254
    ret = output_mak_list('HEADERS', h, 'h')
 
255
    ret += output_mak_list('OBJS', c, 'obj')
 
256
    return ret
 
257
 
 
258
def choose_arch(arch_name):
 
259
    if arch_name == 'x64':
 
260
        return (True,)
 
261
    elif arch_name == 'x86':
 
262
        return (False,)
 
263
    elif arch_name == 'all':
 
264
        return (True, False)
 
265
    else:
 
266
        raise ValueError("architecture ('%s') must be x86, x64, or all" % (arch_name,))
 
267
 
 
268
def rm_rf(dir):
 
269
    print "REMOVE", dir
 
270
    shutil.rmtree(dir, ignore_errors=True)
 
271
 
 
272
def mkdir(dir):
 
273
    print "MKDIR", dir
 
274
    os.mkdir(dir)
 
275
 
 
276
def cp_a(src, dest, dest_is_dir=True):
 
277
    if dest_is_dir:
 
278
        dest = os.path.join(dest, os.path.basename(src))
 
279
    print "COPY_DIR %s %s" % (src, dest)
 
280
    shutil.copytree(src, dest)
 
281
 
 
282
def cp(src, dest, dest_is_dir=True):
 
283
    if dest_is_dir:
 
284
        dest = os.path.join(dest, os.path.basename(src))
 
285
    print "COPY %s %s" % (src, dest)
 
286
    shutil.copyfile(src, dest)
 
287
 
 
288
def rename(src, dest):
 
289
    print "RENAME %s %s" % (src, dest)
 
290
    shutil.move(src, dest)
 
291
 
 
292
def rm_rf(path):
 
293
    try:
 
294
        shutil.rmtree(path, onerror=onerror)
 
295
    except:
 
296
        pass
 
297
 
 
298
def onerror(func, path, exc_info):
 
299
    """
 
300
    Error handler for ``shutil.rmtree``.
 
301
 
 
302
    If the error is due to an access error (read only file)
 
303
    it attempts to add write permission and then retries.
 
304
 
 
305
    If the error is for another reason it re-raises the error.
 
306
 
 
307
    Usage : ``shutil.rmtree(path, onerror=onerror)``
 
308
    """
 
309
    if not os.access(path, os.W_OK):
 
310
        # Is the error an access error ?
 
311
        os.chmod(path, stat.S_IWUSR)
 
312
        func(path)
 
313
    else:
 
314
        raise
 
315
 
 
316
def mkdir_silent(dir):
 
317
    try:
 
318
        os.mkdir(dir)
 
319
    except:
 
320
        pass
 
321
 
 
322
config = get_config()