#!/usr/bin/env ruby # created by Kevin Ballard # based on a script by Michael Conrad Tadpol Tilstra # this script is public domain. require 'rexml/document' require 'strscan' require 'time' # process_description prepares the text by doing proper escaping # and colorizing the crahsed thread and hexadecimal addresses # # We use a throwaway element here to do our escaping for us def process_description(text) pre = REXML::Element.new("pre") text.slice!(/^\*{10}\n\n/) # remove the header ********** text.strip! pre.text = text text = pre.to_s.gsub('&', '&') text.sub!(/\n\nThread \d+ Crashed:\n(?:\d+.*\n)*/) { |m| %{#{m}} } text.gsub!(/\b0x[\da-fA-F]+\b/) { |m| %{#{m}} } text end outf = REXML::Document.new '' outf.elements['/rss/channel'].add_element('title').text = "Crash Reports" outf.elements['/rss/channel'].add_element('generator').text = "showcrashreports.rb" Dir["{#{ENV["HOME"]},}/Library/Logs/CrashReporter/*.crash.log"].each do |crash| if File.stat(crash).readable? reports = File.read(crash).split(/^(?=\*{10}$)/) linenum = 1 reports.each do |report| scanner = StringScanner.new(report) scanner.scan_until(/^Date\/Time:\s+(.*)$/) timestamp = Time.parse(scanner[1]) scanner.scan_until(/^Command:\s+(.*)$/) title = scanner[1] if scanner.scan_until(/^Thread \d+ Crashed:\n(.+)$/) then title += ": #{scanner[1].split(' ',4)[3]}" end item = outf.elements['/rss/channel'].add_element('item') item.add_element('title').text = title item.add_element('pubDate').text = timestamp.rfc822 item.add_element('link').text = "txmt://open/?url=file://#{crash}&line=#{linenum}" item.add_element('description').text = process_description(report) linenum += report.split("\n",-1).length end end end outf.write($stdout, 0)