]> git.ipfire.org Git - people/stevee/selinux-policy.git/blame - support/sedoctool.py
make load target more friendly and add reload target
[people/stevee/selinux-policy.git] / support / sedoctool.py
CommitLineData
89ec2321
CP
1#!/usr/bin/python
2
3# Author: Joshua Brindle <jbrindle@tresys.com>
4#
6b873c4d 5# Copyright (C) 2005 - 2006 Tresys Technology, LLC
89ec2321
CP
6# This program is free software; you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation, version 2.
9
10"""
5a3299bd
CP
11 This module generates configuration files and documentation from the
12 SELinux reference policy XML format.
89ec2321
CP
13"""
14
15import sys
16import getopt
17import pyplate
5a3299bd 18import os
5d941787 19import string
5d941787 20from xml.dom.minidom import parse, parseString
89ec2321 21
2d56fdc2 22#modules enabled and disabled values
f0cc1acd
CP
23MOD_BASE = "base"
24MOD_ENABLED = "module"
2d56fdc2
CP
25MOD_DISABLED = "off"
26
13a4943d
CP
27#booleans enabled and disabled values
28BOOL_ENABLED = "true"
29BOOL_DISABLED = "false"
30
2d56fdc2
CP
31#tunables enabled and disabled values
32TUN_ENABLED = "true"
33TUN_DISABLED = "false"
a4c639dd 34
896badc4 35
89ec2321 36def read_policy_xml(filename):
896badc4
CP
37 """
38 Takes in XML from a file and returns a parsed file.
39 """
40
1601fb37
CP
41 try:
42 xml_fh = open(filename)
43 except:
44 error("error opening " + filename)
45
89ec2321 46 try:
5d941787 47 doc = parseString(xml_fh.read())
89ec2321 48 except:
1601fb37 49 xml_fh.close()
89ec2321 50 error("Error while parsing xml")
1601fb37
CP
51
52 xml_fh.close()
89ec2321
CP
53 return doc
54
13a4943d 55def gen_booleans_conf(doc, file_name, namevalue_list):
896badc4 56 """
13a4943d
CP
57 Generates the booleans configuration file using the XML provided and the
58 previous booleans configuration.
896badc4
CP
59 """
60
13a4943d
CP
61 for node in doc.getElementsByTagName("bool"):
62 for desc in node.getElementsByTagName("desc"):
63 bool_desc = format_txt_desc(desc)
64 s = string.split(bool_desc, "\n")
65 file_name.write("#\n")
66 for line in s:
67 file_name.write("# %s\n" % line)
68
69 bool_name = bool_val = None
70 for (name, value) in node.attributes.items():
71 if name == "name":
72 bool_name = value
73 elif name == "dftval":
74 bool_val = value
75
76 if [bool_name,BOOL_ENABLED] in namevalue_list:
77 bool_val = BOOL_ENABLED
78 elif [bool_name,BOOL_DISABLED] in namevalue_list:
79 bool_val = BOOL_DISABLED
80
81 if bool_name and bool_val:
82 file_name.write("%s = %s\n\n" % (bool_name, bool_val))
83 bool_name = bool_val = None
84
85 # tunables are currently implemented as booleans
89ec2321 86 for node in doc.getElementsByTagName("tunable"):
885b83ec 87 for desc in node.getElementsByTagName("desc"):
13a4943d
CP
88 bool_desc = format_txt_desc(desc)
89 s = string.split(bool_desc, "\n")
885b83ec 90 file_name.write("#\n")
89ec2321 91 for line in s:
f0cc1acd 92 file_name.write("# %s\n" % line)
13a4943d
CP
93
94 bool_name = bool_val = None
95 for (name, value) in node.attributes.items():
5d941787 96 if name == "name":
13a4943d 97 bool_name = value
5d941787 98 elif name == "dftval":
13a4943d 99 bool_val = value
89ec2321 100
13a4943d
CP
101 if [bool_name,BOOL_ENABLED] in namevalue_list:
102 bool_val = BOOL_ENABLED
103 elif [bool_name,BOOL_DISABLED] in namevalue_list:
104 bool_val = BOOL_DISABLED
2d56fdc2 105
13a4943d
CP
106 if bool_name and bool_val:
107 file_name.write("%s = %s\n\n" % (bool_name, bool_val))
108 bool_name = bool_val = None
89ec2321 109
f0cc1acd 110def gen_module_conf(doc, file_name, namevalue_list):
896badc4
CP
111 """
112 Generates the module configuration file using the XML provided and the
113 previous module configuration.
114 """
a4c639dd
CP
115 # If file exists, preserve settings and modify if needed.
116 # Otherwise, create it.
896badc4 117
f0cc1acd
CP
118 file_name.write("#\n# This file contains a listing of available modules.\n")
119 file_name.write("# To prevent a module from being used in policy\n")
120 file_name.write("# creation, set the module name to \"%s\".\n#\n" % MOD_DISABLED)
121 file_name.write("# For monolithic policies, modules set to \"%s\" and \"%s\"\n" % (MOD_BASE, MOD_ENABLED))
122 file_name.write("# will be built into the policy.\n#\n")
123 file_name.write("# For modular policies, modules set to \"%s\" will be\n" % MOD_BASE)
124 file_name.write("# included in the base module. \"%s\" will be compiled\n" % MOD_ENABLED)
125 file_name.write("# as individual loadable modules.\n#\n\n")
126
127 # For required in [True,False] is present so that the requiered modules
128 # are at the top of the config file.
129 for required in [True,False]:
130 for node in doc.getElementsByTagName("module"):
131 mod_req = False
132 for req in node.getElementsByTagName("required"):
133 if req.getAttribute("val") == "true":
134 mod_req = True
135
136 # Skip if we arnt working on the right set of modules.
137 if mod_req and not required or not mod_req and required:
138 continue
5a3299bd 139
5a3299bd 140
f0cc1acd
CP
141 mod_name = mod_layer = None
142
143 mod_name = node.getAttribute("name")
144 mod_layer = node.parentNode.getAttribute("name")
a4c639dd 145
f0cc1acd
CP
146 if mod_name and mod_layer:
147 file_name.write("# Layer: %s\n# Module: %s\n" % (mod_layer,mod_name))
148 if required:
149 file_name.write("# Required in base\n")
150 file_name.write("#\n")
151
152 for desc in node.getElementsByTagName("summary"):
153 if not desc.parentNode == node:
154 continue
155 s = string.split(format_txt_desc(desc), "\n")
156 for line in s:
157 file_name.write("# %s\n" % line)
158
a573790b 159 # If the module is set as disabled.
f0cc1acd
CP
160 if [mod_name, MOD_DISABLED] in namevalue_list:
161 file_name.write("%s = %s\n\n" % (mod_name, MOD_DISABLED))
a573790b 162 # If the module is set as enabled.
f0cc1acd
CP
163 elif [mod_name, MOD_ENABLED] in namevalue_list:
164 file_name.write("%s = %s\n\n" % (mod_name, MOD_ENABLED))
a573790b
CP
165 # If the module is set as base.
166 elif [mod_name, MOD_BASE] in namevalue_list:
f0cc1acd 167 file_name.write("%s = %s\n\n" % (mod_name, MOD_BASE))
a573790b
CP
168 # If the module is a new module.
169 else:
170 # Set the module to base if it is marked as required.
171 if mod_req:
172 file_name.write("%s = %s\n\n" % (mod_name, MOD_BASE))
173 # Set the module to enabled if it is not required.
174 else:
175 file_name.write("%s = %s\n\n" % (mod_name, MOD_ENABLED))
a4c639dd 176
896badc4
CP
177def get_conf(conf):
178 """
179 Returns a list of [name, value] pairs from a config file with the format
180 name = value
181 """
a4c639dd
CP
182
183 conf_lines = conf.readlines()
184
2d56fdc2 185 namevalue_list = []
896badc4
CP
186 for i in range(0,len(conf_lines)):
187 line = conf_lines[i]
a4c639dd 188 if line.strip() != '' and line.strip()[0] != "#":
2d56fdc2 189 namevalue = line.strip().split("=")
896badc4
CP
190 if len(namevalue) != 2:
191 warning("line %d: \"%s\" is not a valid line, skipping"\
192 % (i, line.strip()))
193 continue
194
2d56fdc2 195 namevalue[0] = namevalue[0].strip()
896badc4
CP
196 if len(namevalue[0].split()) > 1:
197 warning("line %d: \"%s\" is not a valid line, skipping"\
198 % (i, line.strip()))
199 continue
200
2d56fdc2 201 namevalue[1] = namevalue[1].strip()
896badc4
CP
202 if len(namevalue[1].split()) > 1:
203 warning("line %d: \"%s\" is not a valid line, skipping"\
204 % (i, line.strip()))
205 continue
206
2d56fdc2 207 namevalue_list.append(namevalue)
2d56fdc2
CP
208
209 return namevalue_list
5a3299bd 210
896badc4
CP
211def first_cmp(a, b):
212 """
213 Compares the two first elements of a list instead of the entire list.
214 """
215
d6b0f371 216 return cmp(a[0], b[0])
d46f0232
CP
217
218def int_cmp(a, b):
896badc4
CP
219 """
220 Compares two interfaces.
221 """
222
d46f0232 223 return cmp(a["interface_name"], b["interface_name"])
effd58c6
CP
224
225def temp_cmp(a, b):
226 """
227 Compares two templates.
228 """
229
230 return cmp(a["template_name"], b["template_name"])
249d461f
CP
231
232def tun_cmp(a, b):
233 """
234 Compares two tunables.
235 """
236
237 return cmp(a["tun_name"], b["tun_name"])
238def bool_cmp(a, b):
239 """
240 Compares two booleans.
241 """
242
243 return cmp(a["bool_name"], b["bool_name"])
244
5a3299bd 245def gen_doc_menu(mod_layer, module_list):
896badc4
CP
246 """
247 Generates the HTML document menu.
248 """
249
d6b0f371
KM
250 menu = []
251 for layer, value in module_list.iteritems():
252 cur_menu = (layer, [])
253 menu.append(cur_menu)
254 if layer != mod_layer and mod_layer != None:
255 continue
5a3299bd 256 #we are in our layer so fill in the other modules or we want them all
d6b0f371
KM
257 for mod, desc in value.iteritems():
258 cur_menu[1].append((mod, desc))
259
896badc4 260 menu.sort(first_cmp)
d6b0f371 261 for x in menu:
896badc4 262 x[1].sort(first_cmp)
5a3299bd
CP
263 return menu
264
fae6ff9a 265def format_html_desc(node):
896badc4
CP
266 """
267 Formats a XML node into a HTML format.
268 """
e214f627
CP
269
270 desc_buf = ''
271 for desc in node.childNodes:
272 if desc.nodeName == "#text":
3c6d78b9 273 if desc.data is not '':
78d30cb1
CP
274 if desc.parentNode.nodeName != "p":
275 desc_buf += "<p>" + desc.data + "</p>"
276 else:
277 desc_buf += desc.data
278 else:
279 desc_buf += "<" + desc.nodeName + ">" \
280 + format_html_desc(desc) \
281 + "</" + desc.nodeName +">"
e214f627
CP
282
283 return desc_buf
284
fae6ff9a 285def format_txt_desc(node):
896badc4
CP
286 """
287 Formats a XML node into a plain text format.
288 """
fae6ff9a
CP
289
290 desc_buf = ''
291 for desc in node.childNodes:
292 if desc.nodeName == "#text":
293 desc_buf += desc.data + "\n"
294 elif desc.nodeName == "p":
295 desc_buf += desc.firstChild.data + "\n"
296 for chld in desc.childNodes:
297 if chld.nodeName == "ul":
298 desc_buf += "\n"
299 for li in chld.getElementsByTagName("li"):
300 desc_buf += "\t -" + li.firstChild.data + "\n"
301
f0cc1acd 302 return desc_buf.strip() + "\n"
e214f627 303
f0cc1acd 304def gen_docs(doc, working_dir, templatedir):
896badc4
CP
305 """
306 Generates all the documentation.
307 """
89ec2321 308
89ec2321 309 try:
d46f0232 310 #get the template data ahead of time so we don't reopen them over and over
5a3299bd
CP
311 bodyfile = open(templatedir + "/header.html", "r")
312 bodydata = bodyfile.read()
313 bodyfile.close()
314 intfile = open(templatedir + "/interface.html", "r")
315 intdata = intfile.read()
316 intfile.close()
effd58c6
CP
317 templatefile = open(templatedir + "/template.html", "r")
318 templatedata = templatefile.read()
319 templatefile.close()
5a3299bd
CP
320 menufile = open(templatedir + "/menu.html", "r")
321 menudata = menufile.read()
322 menufile.close()
323 indexfile = open(templatedir + "/module_list.html","r")
324 indexdata = indexfile.read()
325 indexfile.close()
326 modulefile = open(templatedir + "/module.html","r")
327 moduledata = modulefile.read()
328 modulefile.close()
d46f0232
CP
329 intlistfile = open(templatedir + "/int_list.html", "r")
330 intlistdata = intlistfile.read()
331 intlistfile.close()
effd58c6
CP
332 templistfile = open(templatedir + "/temp_list.html", "r")
333 templistdata = templistfile.read()
334 templistfile.close()
249d461f
CP
335 boollistfile = open(templatedir + "/global_bool_list.html", "r")
336 boollistdata = boollistfile.read()
337 boollistfile.close()
338 tunlistfile = open(templatedir + "/global_tun_list.html", "r")
339 tunlistdata = tunlistfile.read()
340 tunlistfile.close()
89ec2321
CP
341 except:
342 error("Could not open templates")
343
5a3299bd
CP
344
345 try:
f0cc1acd 346 os.chdir(working_dir)
5a3299bd 347 except:
7fb9c1c7 348 error("Could not chdir to target directory")
5a3299bd
CP
349
350
351#arg, i have to go through this dom tree ahead of time to build up the menus
352 module_list = {}
353 for node in doc.getElementsByTagName("module"):
354 mod_name = mod_layer = interface_buf = ''
7fb9c1c7 355
f0cc1acd
CP
356 mod_name = node.getAttribute("name")
357 mod_layer = node.parentNode.getAttribute("name")
7fb9c1c7 358
5a3299bd 359 for desc in node.getElementsByTagName("summary"):
fae6ff9a
CP
360 if desc.parentNode == node and desc:
361 mod_summary = format_html_desc(desc)
5a3299bd
CP
362 if not module_list.has_key(mod_layer):
363 module_list[mod_layer] = {}
364
365 module_list[mod_layer][mod_name] = mod_summary
366
367#generate index pages
368 main_content_buf = ''
369 for mod_layer,modules in module_list.iteritems():
370 menu = gen_doc_menu(mod_layer, module_list)
371
acb668ed
CP
372 layer_summary = None
373 for desc in doc.getElementsByTagName("summary"):
374 if desc.parentNode.getAttribute("name") == mod_layer:
375 layer_summary = format_html_desc(desc)
376
5a3299bd 377 menu_args = { "menulist" : menu,
acb668ed
CP
378 "mod_layer" : mod_layer,
379 "layer_summary" : layer_summary }
5a3299bd
CP
380 menu_tpl = pyplate.Template(menudata)
381 menu_buf = menu_tpl.execute_string(menu_args)
382
383 content_tpl = pyplate.Template(indexdata)
384 content_buf = content_tpl.execute_string(menu_args)
385
386 main_content_buf += content_buf
387
388 body_args = { "menu" : menu_buf,
389 "content" : content_buf }
390
391 index_file = mod_layer + ".html"
392 index_fh = open(index_file, "w")
393 body_tpl = pyplate.Template(bodydata)
394 body_tpl.execute(index_fh, body_args)
395 index_fh.close()
396
397 menu = gen_doc_menu(None, module_list)
398 menu_args = { "menulist" : menu,
399 "mod_layer" : None }
400 menu_tpl = pyplate.Template(menudata)
401 menu_buf = menu_tpl.execute_string(menu_args)
402
403 body_args = { "menu" : menu_buf,
404 "content" : main_content_buf }
405
406 index_file = "index.html"
407 index_fh = open(index_file, "w")
408 body_tpl = pyplate.Template(bodydata)
409 body_tpl.execute(index_fh, body_args)
410 index_fh.close()
d46f0232 411#now generate the individual module pages
89ec2321 412
d46f0232 413 all_interfaces = []
effd58c6 414 all_templates = []
89ec2321 415 for node in doc.getElementsByTagName("module"):
e214f627 416 mod_name = mod_layer = mod_desc = interface_buf = ''
7fb9c1c7 417
f0cc1acd
CP
418 mod_name = node.getAttribute("name")
419 mod_layer = node.parentNode.getAttribute("name")
420
421 mod_req = None
422 for req in node.getElementsByTagName("required"):
423 if req.getAttribute("val") == "true":
424 mod_req = True
7fb9c1c7 425
5a3299bd 426 for desc in node.getElementsByTagName("summary"):
e214f627 427 if desc.parentNode == node:
fae6ff9a 428 mod_summary = format_html_desc(desc)
7c2b84e7 429 for desc in node.getElementsByTagName("desc"):
e214f627 430 if desc.parentNode == node:
fae6ff9a 431 mod_desc = format_html_desc(desc)
d46f0232
CP
432
433 interfaces = []
89ec2321 434 for interface in node.getElementsByTagName("interface"):
5a3299bd 435 interface_parameters = []
d06f3c37 436 interface_desc = interface_summary = None
bff1cef8
CP
437 interface_name = interface.getAttribute("name")
438 interface_line = interface.getAttribute("lineno")
885b83ec
CP
439 for desc in interface.childNodes:
440 if desc.nodeName == "desc":
441 interface_desc = format_html_desc(desc)
442 elif desc.nodeName == "summary":
443 interface_summary = format_html_desc(desc)
444
7c2b84e7 445 for args in interface.getElementsByTagName("param"):
885b83ec
CP
446 for desc in args.getElementsByTagName("summary"):
447 paramdesc = format_html_desc(desc)
bff1cef8
CP
448 paramname = args.getAttribute("name")
449 if args.getAttribute("optional") == "true":
450 paramopt = "Yes"
451 else:
452 paramopt = "No"
5a3299bd
CP
453 parameter = { "name" : paramname,
454 "desc" : paramdesc,
455 "optional" : paramopt }
456 interface_parameters.append(parameter)
d46f0232 457 interfaces.append( { "interface_name" : interface_name,
e214f627 458 "interface_summary" : interface_summary,
5a3299bd 459 "interface_desc" : interface_desc,
d06f3c37 460 "interface_parameters" : interface_parameters })
d46f0232
CP
461 #all_interfaces is for the main interface index with all interfaces
462 all_interfaces.append( { "interface_name" : interface_name,
e214f627 463 "interface_summary" : interface_summary,
d46f0232
CP
464 "interface_desc" : interface_desc,
465 "interface_parameters" : interface_parameters,
d46f0232
CP
466 "mod_name": mod_name,
467 "mod_layer" : mod_layer })
468 interfaces.sort(int_cmp)
469 interface_tpl = pyplate.Template(intdata)
470 interface_buf = interface_tpl.execute_string({"interfaces" : interfaces})
471
effd58c6
CP
472
473# now generate individual template pages
474 templates = []
475 for template in node.getElementsByTagName("template"):
476 template_parameters = []
d06f3c37 477 template_desc = template_summary = None
bff1cef8
CP
478 template_name = template.getAttribute("name")
479 template_line = template.getAttribute("lineno")
885b83ec
CP
480 for desc in template.childNodes:
481 if desc.nodeName == "desc":
482 template_desc = format_html_desc(desc)
483 elif desc.nodeName == "summary":
484 template_summary = format_html_desc(desc)
485
effd58c6 486 for args in template.getElementsByTagName("param"):
885b83ec
CP
487 for desc in args.getElementsByTagName("summary"):
488 paramdesc = format_html_desc(desc)
bff1cef8
CP
489 paramname = args.getAttribute("name")
490 if args.getAttribute("optional") == "true":
491 paramopt = "Yes"
492 else:
493 paramopt = "No"
effd58c6
CP
494 parameter = { "name" : paramname,
495 "desc" : paramdesc,
496 "optional" : paramopt }
497 template_parameters.append(parameter)
498 templates.append( { "template_name" : template_name,
499 "template_summary" : template_summary,
500 "template_desc" : template_desc,
d06f3c37 501 "template_parameters" : template_parameters })
effd58c6
CP
502 #all_templates is for the main interface index with all templates
503 all_templates.append( { "template_name" : template_name,
504 "template_summary" : template_summary,
505 "template_desc" : template_desc,
506 "template_parameters" : template_parameters,
effd58c6
CP
507 "mod_name": mod_name,
508 "mod_layer" : mod_layer })
509
510 templates.sort(temp_cmp)
511 template_tpl = pyplate.Template(templatedata)
512 template_buf = template_tpl.execute_string({"templates" : templates})
513
514
5a3299bd
CP
515 menu = gen_doc_menu(mod_layer, module_list)
516
5a3299bd 517 menu_tpl = pyplate.Template(menudata)
d46f0232 518 menu_buf = menu_tpl.execute_string({ "menulist" : menu })
5a3299bd 519
06c9680d
CP
520
521 # pyplate's execute_string gives us a line of whitespace in
522 # template_buf or interface_buf if there are no interfaces or
523 # templates for this module. This is problematic because the
524 # HTML templates use a conditional if on interface_buf or
525 # template_buf being 'None' to decide if the "Template:" or
526 # "Interface:" headers need to be printed in the module pages.
527 # This detects if either of these are just whitespace, and sets
528 # their values to 'None' so that when applying it to the
529 # templates, they are properly recognized as not existing.
530 if not interface_buf.strip():
531 interface_buf = None
532 if not template_buf.strip():
533 template_buf = None
534
5a3299bd
CP
535 module_args = { "mod_layer" : mod_layer,
536 "mod_name" : mod_name,
537 "mod_summary" : mod_summary,
e214f627 538 "mod_desc" : mod_desc,
f0cc1acd 539 "mod_req" : mod_req,
effd58c6
CP
540 "interfaces" : interface_buf,
541 "templates": template_buf }
5a3299bd
CP
542
543 module_tpl = pyplate.Template(moduledata)
544 module_buf = module_tpl.execute_string(module_args)
545
546 body_args = { "menu" : menu_buf,
547 "content" : module_buf }
548
549 module_file = mod_layer + "_" + mod_name + ".html"
550 module_fh = open(module_file, "w")
551 body_tpl = pyplate.Template(bodydata)
552 body_tpl.execute(module_fh, body_args)
553 module_fh.close()
89ec2321 554
effd58c6 555
249d461f
CP
556 menu = gen_doc_menu(None, module_list)
557 menu_args = { "menulist" : menu,
558 "mod_layer" : None }
559 menu_tpl = pyplate.Template(menudata)
560 menu_buf = menu_tpl.execute_string(menu_args)
d46f0232 561
249d461f
CP
562 #build the interface index
563 all_interfaces.sort(int_cmp)
564 interface_tpl = pyplate.Template(intlistdata)
565 interface_buf = interface_tpl.execute_string({"interfaces" : all_interfaces})
566 int_file = "interfaces.html"
567 int_fh = open(int_file, "w")
568 body_tpl = pyplate.Template(bodydata)
d46f0232 569
249d461f
CP
570 body_args = { "menu" : menu_buf,
571 "content" : interface_buf }
d46f0232 572
249d461f
CP
573 body_tpl.execute(int_fh, body_args)
574 int_fh.close()
d46f0232 575
effd58c6 576
249d461f
CP
577 #build the template index
578 all_templates.sort(temp_cmp)
579 template_tpl = pyplate.Template(templistdata)
580 template_buf = template_tpl.execute_string({"templates" : all_templates})
581 temp_file = "templates.html"
582 temp_fh = open(temp_file, "w")
583 body_tpl = pyplate.Template(bodydata)
584
585 body_args = { "menu" : menu_buf,
586 "content" : template_buf }
587
588 body_tpl.execute(temp_fh, body_args)
589 temp_fh.close()
590
591
592 #build the global tunable index
593 global_tun_buf = []
594 for tunable in doc.getElementsByTagName("tunable"):
595 if tunable.parentNode.nodeName == "policy":
596 tunable_name = tunable.getAttribute("name")
597 default_value = tunable.getAttribute("dftval")
885b83ec
CP
598 for desc in tunable.getElementsByTagName("desc"):
599 description = format_html_desc(desc)
249d461f 600 global_tun_buf.append( { "tun_name" : tunable_name,
4d7511ba
CP
601 "def_val" : default_value,
602 "desc" : description } )
249d461f
CP
603 global_tun_buf.sort(tun_cmp)
604 global_tun_tpl = pyplate.Template(tunlistdata)
605 global_tun_buf = global_tun_tpl.execute_string({"tunables" : global_tun_buf})
606 global_tun_file = "global_tunables.html"
607 global_tun_fh = open(global_tun_file, "w")
608 body_tpl = pyplate.Template(bodydata)
609
610 body_args = { "menu" : menu_buf,
611 "content" : global_tun_buf }
612
613 body_tpl.execute(global_tun_fh, body_args)
614 global_tun_fh.close()
615
616
617 #build the global boolean index
618 global_bool_buf = []
4f9f30c8 619 for boolean in doc.getElementsByTagName("bool"):
249d461f
CP
620 if boolean.parentNode.nodeName == "policy":
621 bool_name = boolean.getAttribute("name")
622 default_value = boolean.getAttribute("dftval")
885b83ec
CP
623 for desc in boolean.getElementsByTagName("desc"):
624 description = format_html_desc(desc)
249d461f 625 global_bool_buf.append( { "bool_name" : bool_name,
4d7511ba
CP
626 "def_val" : default_value,
627 "desc" : description } )
249d461f
CP
628 global_bool_buf.sort(bool_cmp)
629 global_bool_tpl = pyplate.Template(boollistdata)
630 global_bool_buf = global_bool_tpl.execute_string({"booleans" : global_bool_buf})
631 global_bool_file = "global_booleans.html"
632 global_bool_fh = open(global_bool_file, "w")
633 body_tpl = pyplate.Template(bodydata)
634
635 body_args = { "menu" : menu_buf,
636 "content" : global_bool_buf }
637
638 body_tpl.execute(global_bool_fh, body_args)
639 global_bool_fh.close()
effd58c6 640
effd58c6 641
effd58c6 642
89ec2321 643def error(error):
896badc4
CP
644 """
645 Print an error message and exit.
646 """
647
89ec2321
CP
648 sys.stderr.write("%s exiting for: " % sys.argv[0])
649 sys.stderr.write("%s\n" % error)
650 sys.stderr.flush()
651 sys.exit(1)
652
896badc4
CP
653def warning(warn):
654 """
655 Print a warning message.
656 """
657
658 sys.stderr.write("%s warning: " % sys.argv[0])
659 sys.stderr.write("%s\n" % warn)
660
89ec2321 661def usage():
896badc4
CP
662 """
663 Describes the proper usage of this tool.
664 """
665
5a3299bd 666 sys.stdout.write("%s [-tmdT] -x <xmlfile>\n\n" % sys.argv[0])
89ec2321 667 sys.stdout.write("Options:\n")
13a4943d 668 sys.stdout.write("-b --booleans <file> -- write boolean config to <file>\n")
89ec2321
CP
669 sys.stdout.write("-m --modules <file> -- write module config to <file>\n")
670 sys.stdout.write("-d --docs <dir> -- write interface documentation to <dir>\n")
671 sys.stdout.write("-x --xml <file> -- filename to read xml data from\n")
5a3299bd 672 sys.stdout.write("-T --templates <dir> -- template directory for documents\n")
89ec2321 673
896badc4
CP
674
675# MAIN PROGRAM
89ec2321 676try:
13a4943d 677 opts, args = getopt.getopt(sys.argv[1:], "b:m:d:x:T:", ["booleans","modules","docs","xml", "templates"])
89ec2321
CP
678except getopt.GetoptError:
679 usage()
680 sys.exit(1)
681
13a4943d 682booleans = modules = docsdir = None
5a3299bd
CP
683templatedir = "templates/"
684xmlfile = "policy.xml"
89ec2321
CP
685
686for opt, val in opts:
13a4943d
CP
687 if opt in ("-b", "--booleans"):
688 booleans = val
89ec2321
CP
689 if opt in ("-m", "--modules"):
690 modules = val
691 if opt in ("-d", "--docs"):
5a3299bd 692 docsdir = val
89ec2321
CP
693 if opt in ("-x", "--xml"):
694 xmlfile = val
5a3299bd
CP
695 if opt in ("-T", "--templates"):
696 templatedir = val
89ec2321 697
89ec2321
CP
698doc = read_policy_xml(xmlfile)
699
13a4943d 700if booleans:
2d56fdc2 701 namevalue_list = []
13a4943d 702 if os.path.exists(booleans):
2d56fdc2 703 try:
13a4943d 704 conf = open(booleans, 'r')
2d56fdc2 705 except:
13a4943d 706 error("Could not open booleans file for reading")
2d56fdc2 707
896badc4 708 namevalue_list = get_conf(conf)
2d56fdc2
CP
709
710 conf.close()
711
89ec2321 712 try:
13a4943d 713 conf = open(booleans, 'w')
89ec2321 714 except:
13a4943d 715 error("Could not open booleans file for writing")
2d56fdc2 716
13a4943d 717 gen_booleans_conf(doc, conf, namevalue_list)
89ec2321
CP
718 conf.close()
719
720
721if modules:
2d56fdc2 722 namevalue_list = []
a4c639dd
CP
723 if os.path.exists(modules):
724 try:
725 conf = open(modules, 'r')
726 except:
727 error("Could not open modules file for reading")
896badc4 728 namevalue_list = get_conf(conf)
a4c639dd
CP
729 conf.close()
730
89ec2321
CP
731 try:
732 conf = open(modules, 'w')
733 except:
734 error("Could not open modules file for writing")
2d56fdc2 735 gen_module_conf(doc, conf, namevalue_list)
89ec2321
CP
736 conf.close()
737
5a3299bd
CP
738if docsdir:
739 gen_docs(doc, docsdir, templatedir)