xref: /aosp_15_r20/external/mdnsresponder/mDNSPosix/parselog.py (revision 48a54d368dc4fa860885eef7b70b6c53499e7c25)
1*48a54d36SAndroid Build Coastguard Worker#!/usr/bin/python
2*48a54d36SAndroid Build Coastguard Worker# Emacs settings: -*- tab-width: 4 -*-
3*48a54d36SAndroid Build Coastguard Worker#
4*48a54d36SAndroid Build Coastguard Worker# Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
5*48a54d36SAndroid Build Coastguard Worker#
6*48a54d36SAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
7*48a54d36SAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
8*48a54d36SAndroid Build Coastguard Worker# You may obtain a copy of the License at
9*48a54d36SAndroid Build Coastguard Worker#
10*48a54d36SAndroid Build Coastguard Worker#     http://www.apache.org/licenses/LICENSE-2.0
11*48a54d36SAndroid Build Coastguard Worker#
12*48a54d36SAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
13*48a54d36SAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
14*48a54d36SAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15*48a54d36SAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
16*48a54d36SAndroid Build Coastguard Worker# limitations under the License.
17*48a54d36SAndroid Build Coastguard Worker#
18*48a54d36SAndroid Build Coastguard Worker# parselog.py, written and contributed by Kevin Marks
19*48a54d36SAndroid Build Coastguard Worker#
20*48a54d36SAndroid Build Coastguard Worker# Requires OS X 10.3 Panther or later, for Python and Core Graphics Python APIs
21*48a54d36SAndroid Build Coastguard Worker# Invoke from the command line with "parselog.py fname" where fname is a log file made by mDNSNetMonitor
22*48a54d36SAndroid Build Coastguard Worker#
23*48a54d36SAndroid Build Coastguard Worker# Caveats:
24*48a54d36SAndroid Build Coastguard Worker# It expects plain ASCII, and doesn't handle spaces in record names very well right now
25*48a54d36SAndroid Build Coastguard Worker# There's a procedure you can follow to 'sanitize' an mDNSNetMonitor log file to make it more paletable to parselog.py:
26*48a54d36SAndroid Build Coastguard Worker# 1. Run mDNSNetMonitor in a terminal window.
27*48a54d36SAndroid Build Coastguard Worker#    When you have enough traffic, type Ctrl-C and save the content of the terminal window to disk.
28*48a54d36SAndroid Build Coastguard Worker#    Alternatively, you can use "mDNSNetMonitor > logfile" to write the text directly to a file.
29*48a54d36SAndroid Build Coastguard Worker#    You now have a UTF-8 text file.
30*48a54d36SAndroid Build Coastguard Worker# 2. Open the UTF-8 text file using BBEdit or some other text editor.
31*48a54d36SAndroid Build Coastguard Worker#    (These instructions are for BBEdit, which I highly recommend you use when doing this.)
32*48a54d36SAndroid Build Coastguard Worker# 3. Make sure BBEdit correctly interprets the file as UTF-8.
33*48a54d36SAndroid Build Coastguard Worker#    Either set your "Text Files Opening" preference to "UTF-8 no BOM", and drop the file onto BBEdit,
34*48a54d36SAndroid Build Coastguard Worker#    or manually open the File using "File -> Open" and make sure the "Read As" setting is set to "UTF-8 no BOM"
35*48a54d36SAndroid Build Coastguard Worker#    Check in the document pulldown menu in the window toolbar to make sure that it says "Encoding: UTF-8 no BOM"
36*48a54d36SAndroid Build Coastguard Worker# 4. Use "Tools -> Convert to ASCII" to replace all special characters with their seven-bit ascii equivalents.
37*48a54d36SAndroid Build Coastguard Worker#    (e.g. curly quotes are converted to straight quotes)
38*48a54d36SAndroid Build Coastguard Worker# 5. Do a grep search and replace. (Cmd-F; make sure Grep checkbox is turned on.)
39*48a54d36SAndroid Build Coastguard Worker#    Enter this search text     : ^(.................\(................\S*) (.* -> .*)$
40*48a54d36SAndroid Build Coastguard Worker#    Enter this replacement text: \1-\2
41*48a54d36SAndroid Build Coastguard Worker#    Click "Replace All"
42*48a54d36SAndroid Build Coastguard Worker#    Press Cmd-Opt-= repeatedly until there are no more instances to be replaced.
43*48a54d36SAndroid Build Coastguard Worker#    You now have text file with all spaces in names changed to hyphens
44*48a54d36SAndroid Build Coastguard Worker# 6. Save the new file. You can save it as "UTF-8 no BOM", or as "Mac Roman". It really doesn't matter which --
45*48a54d36SAndroid Build Coastguard Worker#    the file now contains only seven-bit ascii, so it's all the same no matter how you save it.
46*48a54d36SAndroid Build Coastguard Worker# 7. Run "parselog.py fname"
47*48a54d36SAndroid Build Coastguard Worker# 8. Open the resulting fname.pdf file with a PDF viewer like Preview on OS X
48*48a54d36SAndroid Build Coastguard Worker#
49*48a54d36SAndroid Build Coastguard Worker# Key to what you see:
50*48a54d36SAndroid Build Coastguard Worker# Time is on the horizontal axis
51*48a54d36SAndroid Build Coastguard Worker# Individual machines are shown on the vertical axis
52*48a54d36SAndroid Build Coastguard Worker# Filled red    circle: Normal query              Hollow red    circle: Query requesting unicast reply
53*48a54d36SAndroid Build Coastguard Worker# Filled orange circle: Probe (service starting)  Hollow orange circle: First probe (requesting unicast reply)
54*48a54d36SAndroid Build Coastguard Worker# Filled green  circle: Normal answer             Hollow green  circle: Goodbye message (record going away)
55*48a54d36SAndroid Build Coastguard Worker#                                                 Hollow blue   circle: Legacy query (from old client)
56*48a54d36SAndroid Build Coastguard Worker
57*48a54d36SAndroid Build Coastguard Workerfrom CoreGraphics import *
58*48a54d36SAndroid Build Coastguard Workerimport math   # for pi
59*48a54d36SAndroid Build Coastguard Worker
60*48a54d36SAndroid Build Coastguard Workerimport string
61*48a54d36SAndroid Build Coastguard Workerimport sys, os
62*48a54d36SAndroid Build Coastguard Workerimport re
63*48a54d36SAndroid Build Coastguard Worker
64*48a54d36SAndroid Build Coastguard Workerdef parselog(inFile):
65*48a54d36SAndroid Build Coastguard Worker	f = open(inFile)
66*48a54d36SAndroid Build Coastguard Worker	hunt = 'getTime'
67*48a54d36SAndroid Build Coastguard Worker	ipList = {}
68*48a54d36SAndroid Build Coastguard Worker	querySource = {}
69*48a54d36SAndroid Build Coastguard Worker	plotPoints = []
70*48a54d36SAndroid Build Coastguard Worker	maxTime=0
71*48a54d36SAndroid Build Coastguard Worker	minTime = 36*60*60
72*48a54d36SAndroid Build Coastguard Worker	spaceExp = re.compile(r'\s+')
73*48a54d36SAndroid Build Coastguard Worker	print "Reading " + inFile
74*48a54d36SAndroid Build Coastguard Worker	while 1:
75*48a54d36SAndroid Build Coastguard Worker		lines = f.readlines(100000)
76*48a54d36SAndroid Build Coastguard Worker		if not lines:
77*48a54d36SAndroid Build Coastguard Worker			break
78*48a54d36SAndroid Build Coastguard Worker		for line in lines:
79*48a54d36SAndroid Build Coastguard Worker			if (hunt == 'skip'):
80*48a54d36SAndroid Build Coastguard Worker				if (line == '\n' or line == '\r' or line ==''):
81*48a54d36SAndroid Build Coastguard Worker					hunt = 'getTime'
82*48a54d36SAndroid Build Coastguard Worker#				else:
83*48a54d36SAndroid Build Coastguard Worker#					msg = ("skipped" , line)
84*48a54d36SAndroid Build Coastguard Worker#					print msg
85*48a54d36SAndroid Build Coastguard Worker			elif (hunt == 'getTime'):
86*48a54d36SAndroid Build Coastguard Worker				if (line == "^C\n" ):
87*48a54d36SAndroid Build Coastguard Worker					break
88*48a54d36SAndroid Build Coastguard Worker				time = line.split(' ')[0].split(':')
89*48a54d36SAndroid Build Coastguard Worker				if (len(time)<3):
90*48a54d36SAndroid Build Coastguard Worker					#print "bad time, skipping",time
91*48a54d36SAndroid Build Coastguard Worker					hunt = 'skip'
92*48a54d36SAndroid Build Coastguard Worker				else:
93*48a54d36SAndroid Build Coastguard Worker					hunt = 'getIP'
94*48a54d36SAndroid Build Coastguard Worker				#print (("getTime:%s" % (line)), time)
95*48a54d36SAndroid Build Coastguard Worker			elif (hunt == 'getIP'):
96*48a54d36SAndroid Build Coastguard Worker				ip = line.split(' ',1)
97*48a54d36SAndroid Build Coastguard Worker				ip = ip[0]
98*48a54d36SAndroid Build Coastguard Worker				secs=0
99*48a54d36SAndroid Build Coastguard Worker				for t in time:
100*48a54d36SAndroid Build Coastguard Worker					secs = secs*60 +float(t)
101*48a54d36SAndroid Build Coastguard Worker				if (secs>maxTime):
102*48a54d36SAndroid Build Coastguard Worker					maxTime=secs
103*48a54d36SAndroid Build Coastguard Worker				if (secs<minTime):
104*48a54d36SAndroid Build Coastguard Worker					minTime=secs
105*48a54d36SAndroid Build Coastguard Worker				if (not ip in ipList):
106*48a54d36SAndroid Build Coastguard Worker					ipList[ip] = [len(ipList), "", ""]
107*48a54d36SAndroid Build Coastguard Worker				#print (("getIP:%s" % (line)), time, secs)
108*48a54d36SAndroid Build Coastguard Worker				hunt = 'getQA'
109*48a54d36SAndroid Build Coastguard Worker			elif (hunt == 'getQA'):
110*48a54d36SAndroid Build Coastguard Worker				qaList = spaceExp.split(line)
111*48a54d36SAndroid Build Coastguard Worker				# qaList[0] Source Address
112*48a54d36SAndroid Build Coastguard Worker				# qaList[1] Operation type (PU/PM/QU/QM/AN etc.)
113*48a54d36SAndroid Build Coastguard Worker				# qaList[2] Record type (PTR/SRV/TXT etc.)
114*48a54d36SAndroid Build Coastguard Worker				# For QU/QM/LQ:
115*48a54d36SAndroid Build Coastguard Worker				# qaList[3] RR name
116*48a54d36SAndroid Build Coastguard Worker				# For PU/PM/AN/AN+/AD/AD+/KA:
117*48a54d36SAndroid Build Coastguard Worker				# qaList[3] TTL
118*48a54d36SAndroid Build Coastguard Worker				# qaList[4] RR name
119*48a54d36SAndroid Build Coastguard Worker				# qaList[5...] "->" symbol and following rdata
120*48a54d36SAndroid Build Coastguard Worker				#print qaList
121*48a54d36SAndroid Build Coastguard Worker				if (qaList[0] == ip):
122*48a54d36SAndroid Build Coastguard Worker					if (qaList[1] == '(QU)' or qaList[1] == '(LQ)' or qaList[1] == '(PU)'):
123*48a54d36SAndroid Build Coastguard Worker						plotPoints.append([secs, ipList[ip][0], (qaList[1])[1:-1]])
124*48a54d36SAndroid Build Coastguard Worker					elif (qaList[1] == '(QM)'):
125*48a54d36SAndroid Build Coastguard Worker						plotPoints.append([secs, ipList[ip][0], (qaList[1])[1:-1]])
126*48a54d36SAndroid Build Coastguard Worker						querySource[qaList[3]] = len(plotPoints)-1
127*48a54d36SAndroid Build Coastguard Worker					elif (qaList[1] == '(PM)'):
128*48a54d36SAndroid Build Coastguard Worker						plotPoints.append([secs, ipList[ip][0], (qaList[1])[1:-1]])
129*48a54d36SAndroid Build Coastguard Worker						querySource[qaList[4]] = len(plotPoints)-1
130*48a54d36SAndroid Build Coastguard Worker					elif (qaList[1] == '(AN)' or qaList[1] == '(AN+)' or qaList[1] == '(DE)'):
131*48a54d36SAndroid Build Coastguard Worker						plotPoints.append([secs, ipList[ip][0], (qaList[1])[1:-1]])
132*48a54d36SAndroid Build Coastguard Worker						try:
133*48a54d36SAndroid Build Coastguard Worker							theQuery = querySource[qaList[4]]
134*48a54d36SAndroid Build Coastguard Worker							theDelta = secs - plotPoints[theQuery][0]
135*48a54d36SAndroid Build Coastguard Worker							if (theDelta < 1.0):
136*48a54d36SAndroid Build Coastguard Worker								plotPoints[-1].append(querySource[qaList[4]])
137*48a54d36SAndroid Build Coastguard Worker							#print "Answer AN+ %s points to %d" % (qaList[4],querySource[qaList[4]])
138*48a54d36SAndroid Build Coastguard Worker						except:
139*48a54d36SAndroid Build Coastguard Worker							#print "Couldn't find any preceeding question for", qaList
140*48a54d36SAndroid Build Coastguard Worker							pass
141*48a54d36SAndroid Build Coastguard Worker					elif (qaList[1] != '(KA)' and qaList[1] != '(AD)' and qaList[1] != '(AD+)'):
142*48a54d36SAndroid Build Coastguard Worker						print "Operation unknown", qaList
143*48a54d36SAndroid Build Coastguard Worker
144*48a54d36SAndroid Build Coastguard Worker					if (qaList[1] == '(AN)' or qaList[1] == '(AN+)' or qaList[1] == '(AD)' or qaList[1] == '(AD+)'):
145*48a54d36SAndroid Build Coastguard Worker						if (qaList[2] == 'HINFO'):
146*48a54d36SAndroid Build Coastguard Worker							ipList[ip][1] = qaList[4]
147*48a54d36SAndroid Build Coastguard Worker							ipList[ip][2] = string.join(qaList[6:])
148*48a54d36SAndroid Build Coastguard Worker							#print ipList[ip][1]
149*48a54d36SAndroid Build Coastguard Worker						elif (qaList[2] == 'AAAA'):
150*48a54d36SAndroid Build Coastguard Worker							if (ipList[ip][1] == ""):
151*48a54d36SAndroid Build Coastguard Worker								ipList[ip][1] = qaList[4]
152*48a54d36SAndroid Build Coastguard Worker								ipList[ip][2] = "Panther"
153*48a54d36SAndroid Build Coastguard Worker						elif (qaList[2] == 'Addr'):
154*48a54d36SAndroid Build Coastguard Worker							if (ipList[ip][1] == ""):
155*48a54d36SAndroid Build Coastguard Worker								ipList[ip][1] = qaList[4]
156*48a54d36SAndroid Build Coastguard Worker								ipList[ip][2] = "Jaguar"
157*48a54d36SAndroid Build Coastguard Worker				else:
158*48a54d36SAndroid Build Coastguard Worker					if (line == '\n'):
159*48a54d36SAndroid Build Coastguard Worker						hunt = 'getTime'
160*48a54d36SAndroid Build Coastguard Worker					else:
161*48a54d36SAndroid Build Coastguard Worker						hunt = 'skip'
162*48a54d36SAndroid Build Coastguard Worker	f.close()
163*48a54d36SAndroid Build Coastguard Worker	#print plotPoints
164*48a54d36SAndroid Build Coastguard Worker	#print querySource
165*48a54d36SAndroid Build Coastguard Worker	#width=20.0*(maxTime-minTime)
166*48a54d36SAndroid Build Coastguard Worker	if (maxTime < minTime + 10.0):
167*48a54d36SAndroid Build Coastguard Worker		maxTime = minTime + 10.0
168*48a54d36SAndroid Build Coastguard Worker	typesize = 12
169*48a54d36SAndroid Build Coastguard Worker	width=20.0*(maxTime-minTime)
170*48a54d36SAndroid Build Coastguard Worker	pageHeight=(len(ipList)+1) * typesize
171*48a54d36SAndroid Build Coastguard Worker	scale = width/(maxTime-minTime)
172*48a54d36SAndroid Build Coastguard Worker	leftMargin = typesize * 60
173*48a54d36SAndroid Build Coastguard Worker	bottomMargin = typesize
174*48a54d36SAndroid Build Coastguard Worker	pageRect = CGRectMake (-leftMargin, -bottomMargin,  leftMargin + width, bottomMargin + pageHeight)   #  landscape
175*48a54d36SAndroid Build Coastguard Worker	outFile = "%s.pdf" % (".".join(inFile.split('.')[:-1]))
176*48a54d36SAndroid Build Coastguard Worker	c = CGPDFContextCreateWithFilename (outFile, pageRect)
177*48a54d36SAndroid Build Coastguard Worker	print "Writing " + outFile
178*48a54d36SAndroid Build Coastguard Worker	ourColourSpace = c.getColorSpace()
179*48a54d36SAndroid Build Coastguard Worker	# QM/QU red    solid/hollow
180*48a54d36SAndroid Build Coastguard Worker	# PM/PU orange solid/hollow
181*48a54d36SAndroid Build Coastguard Worker	# LQ    blue         hollow
182*48a54d36SAndroid Build Coastguard Worker	# AN/DA green  solid/hollow
183*48a54d36SAndroid Build Coastguard Worker	#colourLookup = {"L":(0.0,0.0,.75), "Q":(.75,0.0,0.0), "P":(.75,0.5,0.0), "A":(0.0,0.75,0.0), "D":(0.0,0.75,0.0), "?":(.25,0.25,0.25)}
184*48a54d36SAndroid Build Coastguard Worker	colourLookup = {"L":(0.0,0.0,1.0), "Q":(1.0,0.0,0.0), "P":(1.0,0.8,0.0), "A":(0.0,1.0,0.0), "D":(0.0,1.0,0.0), "?":(1.0,1.0,1.0)}
185*48a54d36SAndroid Build Coastguard Worker	c.beginPage (pageRect)
186*48a54d36SAndroid Build Coastguard Worker	c.setRGBFillColor(.75,0.0,0.0,1.0)
187*48a54d36SAndroid Build Coastguard Worker	c.setRGBStrokeColor(.25,0.75,0.25,1.0)
188*48a54d36SAndroid Build Coastguard Worker	c.setLineWidth(0.25)
189*48a54d36SAndroid Build Coastguard Worker	for point in plotPoints:
190*48a54d36SAndroid Build Coastguard Worker		#c.addArc((point[0]-minTime)*scale,point[1]*typesize+6,5,0,2*math.pi,1)
191*48a54d36SAndroid Build Coastguard Worker		c.addArc((point[0]-minTime)*scale,point[1]*typesize+6,typesize/4,0,2*math.pi,1)
192*48a54d36SAndroid Build Coastguard Worker		theColour = colourLookup[(point[2])[0]]
193*48a54d36SAndroid Build Coastguard Worker		if (((point[2])[0]) != "L") and (((point[2])[0]) != "Q") and (((point[2])[0]) != "P") and (((point[2])[0]) != "A") and (((point[2])[0]) != "D"):
194*48a54d36SAndroid Build Coastguard Worker			print "Unknown", point
195*48a54d36SAndroid Build Coastguard Worker		if ((point[2])[-1] == "M" or (point[2])[0]== "A"):
196*48a54d36SAndroid Build Coastguard Worker			c.setRGBFillColor(theColour[0],theColour[1],theColour[2],.5)
197*48a54d36SAndroid Build Coastguard Worker			c.fillPath()
198*48a54d36SAndroid Build Coastguard Worker		else:
199*48a54d36SAndroid Build Coastguard Worker			c.setRGBStrokeColor(theColour[0],theColour[1],theColour[2],.5)
200*48a54d36SAndroid Build Coastguard Worker			c.setLineWidth(1.0)
201*48a54d36SAndroid Build Coastguard Worker			c.strokePath()
202*48a54d36SAndroid Build Coastguard Worker		c.setRGBStrokeColor(.25,0.75,0.25,1.0)
203*48a54d36SAndroid Build Coastguard Worker		c.setLineWidth(0.25)
204*48a54d36SAndroid Build Coastguard Worker		for index in point[3:]:
205*48a54d36SAndroid Build Coastguard Worker			c.beginPath()
206*48a54d36SAndroid Build Coastguard Worker			c.moveToPoint((point[0]-minTime)*scale,point[1]*typesize+6)
207*48a54d36SAndroid Build Coastguard Worker			c.addLineToPoint(((plotPoints[index])[0]-minTime)*scale,(plotPoints[index])[1]*typesize+6)
208*48a54d36SAndroid Build Coastguard Worker			c.closePath()
209*48a54d36SAndroid Build Coastguard Worker			c.strokePath()
210*48a54d36SAndroid Build Coastguard Worker	c.setRGBFillColor (0,0,0, 1)
211*48a54d36SAndroid Build Coastguard Worker	c.setTextDrawingMode (kCGTextFill)
212*48a54d36SAndroid Build Coastguard Worker	c.setTextMatrix (CGAffineTransformIdentity)
213*48a54d36SAndroid Build Coastguard Worker	c.selectFont ('Gill Sans', typesize, kCGEncodingMacRoman)
214*48a54d36SAndroid Build Coastguard Worker	c.setRGBStrokeColor(0.25,0.0,0.0,1.0)
215*48a54d36SAndroid Build Coastguard Worker	c.setLineWidth(0.1)
216*48a54d36SAndroid Build Coastguard Worker	for ip,[height,hname,hinfo] in ipList.items():
217*48a54d36SAndroid Build Coastguard Worker		c.beginPath()
218*48a54d36SAndroid Build Coastguard Worker		c.moveToPoint(pageRect.origin.x,height*typesize+6)
219*48a54d36SAndroid Build Coastguard Worker		c.addLineToPoint(width,height*typesize+6)
220*48a54d36SAndroid Build Coastguard Worker		c.closePath()
221*48a54d36SAndroid Build Coastguard Worker		c.strokePath()
222*48a54d36SAndroid Build Coastguard Worker		c.showTextAtPoint(pageRect.origin.x + 2,               height*typesize + 2, ip,    len(ip))
223*48a54d36SAndroid Build Coastguard Worker		c.showTextAtPoint(pageRect.origin.x + 2 + typesize*8,  height*typesize + 2, hname, len(hname))
224*48a54d36SAndroid Build Coastguard Worker		c.showTextAtPoint(pageRect.origin.x + 2 + typesize*25, height*typesize + 2, hinfo, len(hinfo))
225*48a54d36SAndroid Build Coastguard Worker	for time in range (int(minTime),int(maxTime)+1):
226*48a54d36SAndroid Build Coastguard Worker		c.beginPath()
227*48a54d36SAndroid Build Coastguard Worker		c.moveToPoint((time-minTime)*scale,pageRect.origin.y)
228*48a54d36SAndroid Build Coastguard Worker		c.addLineToPoint((time-minTime)*scale,pageHeight)
229*48a54d36SAndroid Build Coastguard Worker		c.closePath()
230*48a54d36SAndroid Build Coastguard Worker		if (int(time) % 10 == 0):
231*48a54d36SAndroid Build Coastguard Worker			theHours = time/3600
232*48a54d36SAndroid Build Coastguard Worker			theMinutes = time/60 % 60
233*48a54d36SAndroid Build Coastguard Worker			theSeconds = time % 60
234*48a54d36SAndroid Build Coastguard Worker			theTimeString = '%d:%02d:%02d' % (theHours, theMinutes, theSeconds)
235*48a54d36SAndroid Build Coastguard Worker			# Should measure string width, but don't know how to do that
236*48a54d36SAndroid Build Coastguard Worker			theStringWidth = typesize * 3.5
237*48a54d36SAndroid Build Coastguard Worker			c.showTextAtPoint((time-minTime)*scale - theStringWidth/2, pageRect.origin.y + 2, theTimeString, len(theTimeString))
238*48a54d36SAndroid Build Coastguard Worker			c.setLineWidth(0.3)
239*48a54d36SAndroid Build Coastguard Worker		else:
240*48a54d36SAndroid Build Coastguard Worker			c.setLineWidth(0.1)
241*48a54d36SAndroid Build Coastguard Worker		c.strokePath()
242*48a54d36SAndroid Build Coastguard Worker	c.endPage()
243*48a54d36SAndroid Build Coastguard Worker	c.finish()
244*48a54d36SAndroid Build Coastguard Worker
245*48a54d36SAndroid Build Coastguard Worker
246*48a54d36SAndroid Build Coastguard Workerfor arg in sys.argv[1:]:
247*48a54d36SAndroid Build Coastguard Worker	parselog(arg)
248