1*8b26181fSAndroid Build Coastguard Worker#!/usr/bin/env python 2*8b26181fSAndroid Build Coastguard Worker 3*8b26181fSAndroid Build Coastguard Worker""" 4*8b26181fSAndroid Build Coastguard WorkerThis program parses the output from pcap_compile() to visualize the CFG after 5*8b26181fSAndroid Build Coastguard Workereach optimize phase. 6*8b26181fSAndroid Build Coastguard Worker 7*8b26181fSAndroid Build Coastguard WorkerUsage guide: 8*8b26181fSAndroid Build Coastguard Worker1. Enable optimizer debugging code when configure libpcap, 9*8b26181fSAndroid Build Coastguard Worker and build libpcap & the test programs 10*8b26181fSAndroid Build Coastguard Worker ./configure --enable-optimizer-dbg 11*8b26181fSAndroid Build Coastguard Worker make 12*8b26181fSAndroid Build Coastguard Worker make testprogs 13*8b26181fSAndroid Build Coastguard Worker2. Run filtertest to compile BPF expression and produce the CFG as a 14*8b26181fSAndroid Build Coastguard Worker DOT graph, save to output a.txt 15*8b26181fSAndroid Build Coastguard Worker testprogs/filtertest -g EN10MB host 192.168.1.1 > a.txt 16*8b26181fSAndroid Build Coastguard Worker3. Send a.txt to this program's standard input 17*8b26181fSAndroid Build Coastguard Worker cat a.txt | testprogs/visopts.py 18*8b26181fSAndroid Build Coastguard Worker (Graphviz must be installed) 19*8b26181fSAndroid Build Coastguard Worker4. Step 2&3 can be merged: 20*8b26181fSAndroid Build Coastguard Worker testprogs/filtertest -g EN10MB host 192.168.1.1 | testprogs/visopts.py 21*8b26181fSAndroid Build Coastguard Worker5. The standard output is something like this: 22*8b26181fSAndroid Build Coastguard Worker generated files under directory: /tmp/visopts-W9ekBw 23*8b26181fSAndroid Build Coastguard Worker the directory will be removed when this programs finished. 24*8b26181fSAndroid Build Coastguard Worker open this link: http://localhost:39062/expr1.html 25*8b26181fSAndroid Build Coastguard Worker6. Open the URL at the 3rd line in a browser. 26*8b26181fSAndroid Build Coastguard Worker 27*8b26181fSAndroid Build Coastguard WorkerNote: 28*8b26181fSAndroid Build Coastguard Worker1. The CFG is translated to SVG images, expr1.html embeds them as external 29*8b26181fSAndroid Build Coastguard Worker documents. If you open expr1.html as local file using file:// protocol, some 30*8b26181fSAndroid Build Coastguard Worker browsers will deny such requests so the web page will not work properly. 31*8b26181fSAndroid Build Coastguard Worker For Chrome, you can run it using the following command to avoid this: 32*8b26181fSAndroid Build Coastguard Worker chromium --disable-web-security 33*8b26181fSAndroid Build Coastguard Worker That's why this program starts a localhost HTTP server. 34*8b26181fSAndroid Build Coastguard Worker2. expr1.html uses jQuery from https://ajax.googleapis.com, so it needs Internet 35*8b26181fSAndroid Build Coastguard Worker access to work. 36*8b26181fSAndroid Build Coastguard Worker""" 37*8b26181fSAndroid Build Coastguard Worker 38*8b26181fSAndroid Build Coastguard Workerimport sys, os 39*8b26181fSAndroid Build Coastguard Workerimport string 40*8b26181fSAndroid Build Coastguard Workerimport subprocess 41*8b26181fSAndroid Build Coastguard Workerimport json 42*8b26181fSAndroid Build Coastguard Worker 43*8b26181fSAndroid Build Coastguard Workerhtml_template = string.Template(""" 44*8b26181fSAndroid Build Coastguard Worker<html> 45*8b26181fSAndroid Build Coastguard Worker <head> 46*8b26181fSAndroid Build Coastguard Worker <title>BPF compiler optimization phases for $expr </title> 47*8b26181fSAndroid Build Coastguard Worker <style type="text/css"> 48*8b26181fSAndroid Build Coastguard Worker .hc { 49*8b26181fSAndroid Build Coastguard Worker /* half width container */ 50*8b26181fSAndroid Build Coastguard Worker display: inline-block; 51*8b26181fSAndroid Build Coastguard Worker float: left; 52*8b26181fSAndroid Build Coastguard Worker width: 50%; 53*8b26181fSAndroid Build Coastguard Worker } 54*8b26181fSAndroid Build Coastguard Worker </style> 55*8b26181fSAndroid Build Coastguard Worker 56*8b26181fSAndroid Build Coastguard Worker <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"/></script> 57*8b26181fSAndroid Build Coastguard Worker <!--script type="text/javascript" src="./jquery.min.js"/></script--> 58*8b26181fSAndroid Build Coastguard Worker <script type="text/javascript"> 59*8b26181fSAndroid Build Coastguard Worker var expr = '$expr'; 60*8b26181fSAndroid Build Coastguard Worker var exprid = 1; 61*8b26181fSAndroid Build Coastguard Worker var gcount = $gcount; 62*8b26181fSAndroid Build Coastguard Worker var logs = JSON.parse('$logs'); 63*8b26181fSAndroid Build Coastguard Worker logs[gcount] = ""; 64*8b26181fSAndroid Build Coastguard Worker 65*8b26181fSAndroid Build Coastguard Worker var leftsvg = null; 66*8b26181fSAndroid Build Coastguard Worker var rightsvg = null; 67*8b26181fSAndroid Build Coastguard Worker 68*8b26181fSAndroid Build Coastguard Worker function gurl(index) { 69*8b26181fSAndroid Build Coastguard Worker index += 1; 70*8b26181fSAndroid Build Coastguard Worker if (index < 10) 71*8b26181fSAndroid Build Coastguard Worker s = "00" + index; 72*8b26181fSAndroid Build Coastguard Worker else if (index < 100) 73*8b26181fSAndroid Build Coastguard Worker s = "0" + index; 74*8b26181fSAndroid Build Coastguard Worker else 75*8b26181fSAndroid Build Coastguard Worker s = "" + index; 76*8b26181fSAndroid Build Coastguard Worker return "./expr" + exprid + "_g" + s + ".svg" 77*8b26181fSAndroid Build Coastguard Worker } 78*8b26181fSAndroid Build Coastguard Worker 79*8b26181fSAndroid Build Coastguard Worker function annotate_svgs() { 80*8b26181fSAndroid Build Coastguard Worker if (!leftsvg || !rightsvg) return; 81*8b26181fSAndroid Build Coastguard Worker 82*8b26181fSAndroid Build Coastguard Worker $$.each([$$(leftsvg), $$(rightsvg)], function() { 83*8b26181fSAndroid Build Coastguard Worker $$(this).find("[id|='block'][opacity]").each(function() { 84*8b26181fSAndroid Build Coastguard Worker $$(this).removeAttr('opacity'); 85*8b26181fSAndroid Build Coastguard Worker }); 86*8b26181fSAndroid Build Coastguard Worker }); 87*8b26181fSAndroid Build Coastguard Worker 88*8b26181fSAndroid Build Coastguard Worker $$(leftsvg).find("[id|='block']").each(function() { 89*8b26181fSAndroid Build Coastguard Worker var has = $$(rightsvg).find("#" + this.id).length != 0; 90*8b26181fSAndroid Build Coastguard Worker if (!has) $$(this).attr("opacity", "0.4"); 91*8b26181fSAndroid Build Coastguard Worker else { 92*8b26181fSAndroid Build Coastguard Worker $$(this).click(function() { 93*8b26181fSAndroid Build Coastguard Worker var target = $$(rightsvg).find("#" + this.id); 94*8b26181fSAndroid Build Coastguard Worker var offset = $$("#rightsvgc").offset().top + target.position().top; 95*8b26181fSAndroid Build Coastguard Worker window.scrollTo(0, offset); 96*8b26181fSAndroid Build Coastguard Worker target.focus(); 97*8b26181fSAndroid Build Coastguard Worker }); 98*8b26181fSAndroid Build Coastguard Worker } 99*8b26181fSAndroid Build Coastguard Worker }); 100*8b26181fSAndroid Build Coastguard Worker $$(rightsvg).find("[id|='block']").each(function() { 101*8b26181fSAndroid Build Coastguard Worker var has = $$(leftsvg).find("#" + this.id).length != 0; 102*8b26181fSAndroid Build Coastguard Worker if (!has) $$(this).attr("opacity", "0.4"); 103*8b26181fSAndroid Build Coastguard Worker else { 104*8b26181fSAndroid Build Coastguard Worker $$(this).click(function() { 105*8b26181fSAndroid Build Coastguard Worker var target = $$(leftsvg).find("#" + this.id); 106*8b26181fSAndroid Build Coastguard Worker var offset = $$("#leftsvgc").offset().top + target.position().top; 107*8b26181fSAndroid Build Coastguard Worker window.scrollTo(0, offset); 108*8b26181fSAndroid Build Coastguard Worker target.focus(); 109*8b26181fSAndroid Build Coastguard Worker }); 110*8b26181fSAndroid Build Coastguard Worker } 111*8b26181fSAndroid Build Coastguard Worker }); 112*8b26181fSAndroid Build Coastguard Worker } 113*8b26181fSAndroid Build Coastguard Worker 114*8b26181fSAndroid Build Coastguard Worker function init_svgroot(svg) { 115*8b26181fSAndroid Build Coastguard Worker svg.setAttribute("width", "100%"); 116*8b26181fSAndroid Build Coastguard Worker svg.setAttribute("height", "100%"); 117*8b26181fSAndroid Build Coastguard Worker } 118*8b26181fSAndroid Build Coastguard Worker function wait_leftsvg() { 119*8b26181fSAndroid Build Coastguard Worker if (leftsvg) return; 120*8b26181fSAndroid Build Coastguard Worker var doc = document.getElementById("leftsvgc").getSVGDocument(); 121*8b26181fSAndroid Build Coastguard Worker if (doc == null) { 122*8b26181fSAndroid Build Coastguard Worker setTimeout(wait_leftsvg, 500); 123*8b26181fSAndroid Build Coastguard Worker return; 124*8b26181fSAndroid Build Coastguard Worker } 125*8b26181fSAndroid Build Coastguard Worker leftsvg = doc.documentElement; 126*8b26181fSAndroid Build Coastguard Worker //console.log(leftsvg); 127*8b26181fSAndroid Build Coastguard Worker // initialize it 128*8b26181fSAndroid Build Coastguard Worker init_svgroot(leftsvg); 129*8b26181fSAndroid Build Coastguard Worker annotate_svgs(); 130*8b26181fSAndroid Build Coastguard Worker } 131*8b26181fSAndroid Build Coastguard Worker function wait_rightsvg() { 132*8b26181fSAndroid Build Coastguard Worker if (rightsvg) return; 133*8b26181fSAndroid Build Coastguard Worker var doc = document.getElementById("rightsvgc").getSVGDocument(); 134*8b26181fSAndroid Build Coastguard Worker if (doc == null) { 135*8b26181fSAndroid Build Coastguard Worker setTimeout(wait_rightsvg, 500); 136*8b26181fSAndroid Build Coastguard Worker return; 137*8b26181fSAndroid Build Coastguard Worker } 138*8b26181fSAndroid Build Coastguard Worker rightsvg = doc.documentElement; 139*8b26181fSAndroid Build Coastguard Worker //console.log(rightsvg); 140*8b26181fSAndroid Build Coastguard Worker // initialize it 141*8b26181fSAndroid Build Coastguard Worker init_svgroot(rightsvg); 142*8b26181fSAndroid Build Coastguard Worker annotate_svgs(); 143*8b26181fSAndroid Build Coastguard Worker } 144*8b26181fSAndroid Build Coastguard Worker function load_left(index) { 145*8b26181fSAndroid Build Coastguard Worker var url = gurl(index); 146*8b26181fSAndroid Build Coastguard Worker var frag = "<embed id='leftsvgc' type='image/svg+xml' pluginspage='https://www.adobe.com/svg/viewer/install/' src='" + url + "'/>"; 147*8b26181fSAndroid Build Coastguard Worker $$("#lsvg").html(frag); 148*8b26181fSAndroid Build Coastguard Worker $$("#lcomment").html(logs[index]); 149*8b26181fSAndroid Build Coastguard Worker $$("#lsvglink").attr("href", url); 150*8b26181fSAndroid Build Coastguard Worker leftsvg = null; 151*8b26181fSAndroid Build Coastguard Worker wait_leftsvg(); 152*8b26181fSAndroid Build Coastguard Worker } 153*8b26181fSAndroid Build Coastguard Worker function load_right(index) { 154*8b26181fSAndroid Build Coastguard Worker var url = gurl(index); 155*8b26181fSAndroid Build Coastguard Worker var frag = "<embed id='rightsvgc' type='image/svg+xml' pluginspage='https://www.adobe.com/svg/viewer/install/' src='" + url + "'/>"; 156*8b26181fSAndroid Build Coastguard Worker $$("#rsvg").html(frag); 157*8b26181fSAndroid Build Coastguard Worker $$("#rcomment").html(logs[index]); 158*8b26181fSAndroid Build Coastguard Worker $$("#rsvglink").attr("href", url); 159*8b26181fSAndroid Build Coastguard Worker rightsvg = null; 160*8b26181fSAndroid Build Coastguard Worker wait_rightsvg(); 161*8b26181fSAndroid Build Coastguard Worker } 162*8b26181fSAndroid Build Coastguard Worker 163*8b26181fSAndroid Build Coastguard Worker $$(document).ready(function() { 164*8b26181fSAndroid Build Coastguard Worker for (var i = 0; i < gcount; i++) { 165*8b26181fSAndroid Build Coastguard Worker var opt = "<option value='" + i + "'>loop" + i + " -- " + logs[i] + "</option>"; 166*8b26181fSAndroid Build Coastguard Worker $$("#lselect").append(opt); 167*8b26181fSAndroid Build Coastguard Worker $$("#rselect").append(opt); 168*8b26181fSAndroid Build Coastguard Worker } 169*8b26181fSAndroid Build Coastguard Worker var on_selected = function() { 170*8b26181fSAndroid Build Coastguard Worker var index = parseInt($$(this).children("option:selected").val()); 171*8b26181fSAndroid Build Coastguard Worker if (this.id == "lselect") 172*8b26181fSAndroid Build Coastguard Worker load_left(index); 173*8b26181fSAndroid Build Coastguard Worker else 174*8b26181fSAndroid Build Coastguard Worker load_right(index); 175*8b26181fSAndroid Build Coastguard Worker } 176*8b26181fSAndroid Build Coastguard Worker $$("#lselect").change(on_selected); 177*8b26181fSAndroid Build Coastguard Worker $$("#rselect").change(on_selected); 178*8b26181fSAndroid Build Coastguard Worker 179*8b26181fSAndroid Build Coastguard Worker $$("#backward").click(function() { 180*8b26181fSAndroid Build Coastguard Worker var index = parseInt($$("#lselect option:selected").val()); 181*8b26181fSAndroid Build Coastguard Worker if (index <= 0) return; 182*8b26181fSAndroid Build Coastguard Worker $$("#lselect").val(index - 1).change(); 183*8b26181fSAndroid Build Coastguard Worker $$("#rselect").val(index).change(); 184*8b26181fSAndroid Build Coastguard Worker }); 185*8b26181fSAndroid Build Coastguard Worker $$("#forward").click(function() { 186*8b26181fSAndroid Build Coastguard Worker var index = parseInt($$("#rselect option:selected").val()); 187*8b26181fSAndroid Build Coastguard Worker if (index >= gcount - 1) return; 188*8b26181fSAndroid Build Coastguard Worker $$("#lselect").val(index).change(); 189*8b26181fSAndroid Build Coastguard Worker $$("#rselect").val(index + 1).change(); 190*8b26181fSAndroid Build Coastguard Worker }); 191*8b26181fSAndroid Build Coastguard Worker 192*8b26181fSAndroid Build Coastguard Worker if (gcount >= 1) $$("#lselect").val(0).change(); 193*8b26181fSAndroid Build Coastguard Worker if (gcount >= 2) $$("#rselect").val(1).change(); 194*8b26181fSAndroid Build Coastguard Worker }); 195*8b26181fSAndroid Build Coastguard Worker </script> 196*8b26181fSAndroid Build Coastguard Worker </head> 197*8b26181fSAndroid Build Coastguard Worker <body style="width: 96%"> 198*8b26181fSAndroid Build Coastguard Worker <div> 199*8b26181fSAndroid Build Coastguard Worker <h1>$expr</h1> 200*8b26181fSAndroid Build Coastguard Worker <div style="text-align: center;"> 201*8b26181fSAndroid Build Coastguard Worker <button id="backward" type="button"><<</button> 202*8b26181fSAndroid Build Coastguard Worker 203*8b26181fSAndroid Build Coastguard Worker <button id="forward" type="button">>></button> 204*8b26181fSAndroid Build Coastguard Worker </div> 205*8b26181fSAndroid Build Coastguard Worker </div> 206*8b26181fSAndroid Build Coastguard Worker <br/> 207*8b26181fSAndroid Build Coastguard Worker <div style="clear: both;"> 208*8b26181fSAndroid Build Coastguard Worker <div class="hc lc"> 209*8b26181fSAndroid Build Coastguard Worker <select id="lselect"></select> 210*8b26181fSAndroid Build Coastguard Worker <a id="lsvglink" target="_blank">open this svg in browser</a> 211*8b26181fSAndroid Build Coastguard Worker <p id="lcomment"></p> 212*8b26181fSAndroid Build Coastguard Worker </div> 213*8b26181fSAndroid Build Coastguard Worker <div class="hc rc"> 214*8b26181fSAndroid Build Coastguard Worker <select id="rselect"></select> 215*8b26181fSAndroid Build Coastguard Worker <a id="rsvglink" target="_blank">open this svg in browser</a> 216*8b26181fSAndroid Build Coastguard Worker <p id="rcomment"></p> 217*8b26181fSAndroid Build Coastguard Worker </div> 218*8b26181fSAndroid Build Coastguard Worker </div> 219*8b26181fSAndroid Build Coastguard Worker <br/> 220*8b26181fSAndroid Build Coastguard Worker <div style="clear: both;"> 221*8b26181fSAndroid Build Coastguard Worker <div id="lsvg" class="hc lc"></div> 222*8b26181fSAndroid Build Coastguard Worker <div id="rsvg" class="hc rc"></div> 223*8b26181fSAndroid Build Coastguard Worker </div> 224*8b26181fSAndroid Build Coastguard Worker </body> 225*8b26181fSAndroid Build Coastguard Worker</html> 226*8b26181fSAndroid Build Coastguard Worker""") 227*8b26181fSAndroid Build Coastguard Worker 228*8b26181fSAndroid Build Coastguard Workerdef write_html(expr, gcount, logs): 229*8b26181fSAndroid Build Coastguard Worker logs = map(lambda s: s.strip().replace("\n", "<br/>"), logs) 230*8b26181fSAndroid Build Coastguard Worker 231*8b26181fSAndroid Build Coastguard Worker global html_template 232*8b26181fSAndroid Build Coastguard Worker html = html_template.safe_substitute(expr=expr.encode("string-escape"), gcount=gcount, logs=json.dumps(logs).encode("string-escape")) 233*8b26181fSAndroid Build Coastguard Worker with file("expr1.html", "wt") as f: 234*8b26181fSAndroid Build Coastguard Worker f.write(html) 235*8b26181fSAndroid Build Coastguard Worker 236*8b26181fSAndroid Build Coastguard Workerdef render_on_html(infile): 237*8b26181fSAndroid Build Coastguard Worker expr = None 238*8b26181fSAndroid Build Coastguard Worker gid = 1 239*8b26181fSAndroid Build Coastguard Worker log = "" 240*8b26181fSAndroid Build Coastguard Worker dot = "" 241*8b26181fSAndroid Build Coastguard Worker indot = 0 242*8b26181fSAndroid Build Coastguard Worker logs = [] 243*8b26181fSAndroid Build Coastguard Worker 244*8b26181fSAndroid Build Coastguard Worker for line in infile: 245*8b26181fSAndroid Build Coastguard Worker if line.startswith("machine codes for filter:"): 246*8b26181fSAndroid Build Coastguard Worker expr = line[len("machine codes for filter:"):].strip() 247*8b26181fSAndroid Build Coastguard Worker break 248*8b26181fSAndroid Build Coastguard Worker elif line.startswith("digraph BPF {"): 249*8b26181fSAndroid Build Coastguard Worker indot = 1 250*8b26181fSAndroid Build Coastguard Worker dot = line 251*8b26181fSAndroid Build Coastguard Worker elif indot: 252*8b26181fSAndroid Build Coastguard Worker dot += line 253*8b26181fSAndroid Build Coastguard Worker if line.startswith("}"): 254*8b26181fSAndroid Build Coastguard Worker indot = 2 255*8b26181fSAndroid Build Coastguard Worker else: 256*8b26181fSAndroid Build Coastguard Worker log += line 257*8b26181fSAndroid Build Coastguard Worker 258*8b26181fSAndroid Build Coastguard Worker if indot == 2: 259*8b26181fSAndroid Build Coastguard Worker try: 260*8b26181fSAndroid Build Coastguard Worker p = subprocess.Popen(['dot', '-Tsvg'], stdin=subprocess.PIPE, stdout=subprocess.PIPE) 261*8b26181fSAndroid Build Coastguard Worker except OSError as ose: 262*8b26181fSAndroid Build Coastguard Worker print "Failed to run 'dot':", ose 263*8b26181fSAndroid Build Coastguard Worker print "(Is Graphviz installed?)" 264*8b26181fSAndroid Build Coastguard Worker exit(1) 265*8b26181fSAndroid Build Coastguard Worker 266*8b26181fSAndroid Build Coastguard Worker svg = p.communicate(dot)[0] 267*8b26181fSAndroid Build Coastguard Worker with file("expr1_g%03d.svg" % (gid), "wt") as f: 268*8b26181fSAndroid Build Coastguard Worker f.write(svg) 269*8b26181fSAndroid Build Coastguard Worker 270*8b26181fSAndroid Build Coastguard Worker logs.append(log) 271*8b26181fSAndroid Build Coastguard Worker gid += 1 272*8b26181fSAndroid Build Coastguard Worker log = "" 273*8b26181fSAndroid Build Coastguard Worker dot = "" 274*8b26181fSAndroid Build Coastguard Worker indot = 0 275*8b26181fSAndroid Build Coastguard Worker 276*8b26181fSAndroid Build Coastguard Worker if indot != 0: 277*8b26181fSAndroid Build Coastguard Worker #unterminated dot graph for expression 278*8b26181fSAndroid Build Coastguard Worker return False 279*8b26181fSAndroid Build Coastguard Worker if expr is None: 280*8b26181fSAndroid Build Coastguard Worker # BPF parser encounter error(s) 281*8b26181fSAndroid Build Coastguard Worker return False 282*8b26181fSAndroid Build Coastguard Worker write_html(expr, gid - 1, logs) 283*8b26181fSAndroid Build Coastguard Worker return True 284*8b26181fSAndroid Build Coastguard Worker 285*8b26181fSAndroid Build Coastguard Workerdef run_httpd(): 286*8b26181fSAndroid Build Coastguard Worker import SimpleHTTPServer 287*8b26181fSAndroid Build Coastguard Worker import SocketServer 288*8b26181fSAndroid Build Coastguard Worker 289*8b26181fSAndroid Build Coastguard Worker class MySocketServer(SocketServer.TCPServer): 290*8b26181fSAndroid Build Coastguard Worker allow_reuse_address = True 291*8b26181fSAndroid Build Coastguard Worker Handler = SimpleHTTPServer.SimpleHTTPRequestHandler 292*8b26181fSAndroid Build Coastguard Worker httpd = MySocketServer(("localhost", 0), Handler) 293*8b26181fSAndroid Build Coastguard Worker print "open this link: http://localhost:%d/expr1.html" % (httpd.server_address[1]) 294*8b26181fSAndroid Build Coastguard Worker try: 295*8b26181fSAndroid Build Coastguard Worker httpd.serve_forever() 296*8b26181fSAndroid Build Coastguard Worker except KeyboardInterrupt as e: 297*8b26181fSAndroid Build Coastguard Worker pass 298*8b26181fSAndroid Build Coastguard Worker 299*8b26181fSAndroid Build Coastguard Workerdef main(): 300*8b26181fSAndroid Build Coastguard Worker import tempfile 301*8b26181fSAndroid Build Coastguard Worker import atexit 302*8b26181fSAndroid Build Coastguard Worker import shutil 303*8b26181fSAndroid Build Coastguard Worker os.chdir(tempfile.mkdtemp(prefix="visopts-")) 304*8b26181fSAndroid Build Coastguard Worker atexit.register(shutil.rmtree, os.getcwd()) 305*8b26181fSAndroid Build Coastguard Worker print "generated files under directory: %s" % os.getcwd() 306*8b26181fSAndroid Build Coastguard Worker print " the directory will be removed when this program has finished." 307*8b26181fSAndroid Build Coastguard Worker 308*8b26181fSAndroid Build Coastguard Worker if not render_on_html(sys.stdin): 309*8b26181fSAndroid Build Coastguard Worker return 1 310*8b26181fSAndroid Build Coastguard Worker run_httpd() 311*8b26181fSAndroid Build Coastguard Worker return 0 312*8b26181fSAndroid Build Coastguard Worker 313*8b26181fSAndroid Build Coastguard Workerif __name__ == "__main__": 314*8b26181fSAndroid Build Coastguard Worker if '-h' in sys.argv or '--help' in sys.argv: 315*8b26181fSAndroid Build Coastguard Worker print __doc__ 316*8b26181fSAndroid Build Coastguard Worker exit(0) 317*8b26181fSAndroid Build Coastguard Worker exit(main()) 318