<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="/stylesheets/rss.css" type="text/css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>scattrbrain</title>
    <link>http://scattrbrain.com/</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Darshan Patil's personal blog</description>
    <item>
      <title>Super fast cache for webservice clients in Ruby</title>
      <description>&lt;p&gt;I implemented a cache on my website for the AllPosters.com webservice. Instead of caching the raw response from the webservice, I cache the model constructed after parsing the results. The speedup I get on a cache hit is ridiculous because I don&amp;#8217;t need to parse data anymore.&lt;/p&gt;


	&lt;p&gt;My secret weapon was &lt;span class="caps"&gt;YAML&lt;/span&gt;. All I do is take the model constructed after parsing the data and call to_yaml on it. On a cache hit, I simply call &lt;span class="caps"&gt;YAML&lt;/span&gt;::load. Here is the code. Let me know if this can be improved.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;digest/sha1&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;yaml&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;

&lt;span class="keyword"&gt;module &lt;/span&gt;&lt;span class="module"&gt;Utils&lt;/span&gt;
  &lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Cache&lt;/span&gt;
    &lt;span class="attribute"&gt;@@cache_dir&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;./cache/&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;

    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.write&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;keywords&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;data&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;open&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="attribute"&gt;@@cache_dir&lt;/span&gt; &lt;span class="punct"&gt;+&lt;/span&gt; &lt;span class="ident"&gt;digest&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;keywords&lt;/span&gt;&lt;span class="punct"&gt;),&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;w&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;f&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;f&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;write&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;data&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;to_yaml&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;

    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.cached?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;keywords&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;exists?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="attribute"&gt;@@cache_dir&lt;/span&gt; &lt;span class="punct"&gt;+&lt;/span&gt; &lt;span class="ident"&gt;digest&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;keywords&lt;/span&gt;&lt;span class="punct"&gt;))&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;

    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.read&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;keywords&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="constant"&gt;YAML&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="ident"&gt;load&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;open&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="attribute"&gt;@@cache_dir&lt;/span&gt; &lt;span class="punct"&gt;+&lt;/span&gt; &lt;span class="ident"&gt;digest&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;keywords&lt;/span&gt;&lt;span class="punct"&gt;)))&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;

    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.expire&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;keywords&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;delete&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;digest&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;keywords&lt;/span&gt;&lt;span class="punct"&gt;))&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;

    &lt;span class="ident"&gt;private&lt;/span&gt;
    &lt;span class="attribute"&gt;@@lookup&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;{}&lt;/span&gt;
    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.digest&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;keywords&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="attribute"&gt;@@lookup&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;keywords&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="punct"&gt;||=&lt;/span&gt; &lt;span class="constant"&gt;Digest&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;SHA1&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;hexdigest&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;keywords&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
      <pubDate>Sat, 08 Dec 2007 01:36:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:ae4f40f9-fa3e-4dea-8c6e-f37b98f6ce99</guid>
      <author>dapatil@scattrbrain.com (Darshan Patil)</author>
      <link>http://scattrbrain.com/articles/2007/12/08/super-fast-cache-for-webservice-clients-in-ruby</link>
      <category>Ruby</category>
      <category>Programming</category>
      <category>ruby</category>
      <category>programming</category>
      <category>caching</category>
      <category>fast</category>
      <trackback:ping>http://scattrbrain.com/articles/trackback/253</trackback:ping>
    </item>
    <item>
      <title>Debugging Rails</title>
      <description>&lt;p&gt;script/breakpointer does not work anymore with the latest stable version of rails. The new way to debug rails applications is to use ruby-debug. To use this to debug your rails applications, do the following&lt;/p&gt;


&lt;pre&gt;
gem install ruby-debug
&lt;/pre&gt;

	&lt;p&gt;Once, that is done, edit config/environments/development.rb in your rails application and add the following line to the end of the file.&lt;/p&gt;


&lt;pre&gt;
require 'ruby-debug' 
&lt;/pre&gt;

	&lt;p&gt;To break into the debugger, you need to call&lt;/p&gt;


&lt;pre&gt;
debugger()
&lt;/pre&gt;

	&lt;p&gt;where you would have previously called breakpoint(). When debugger() is executed, the server will break into the debugger. Run &lt;b&gt;help&lt;/b&gt; to see a list of available commands. You can also launch an irb process by typing &lt;b&gt;irb&lt;/b&gt; at the debugger prompt.&lt;/p&gt;


	&lt;p&gt;Note:
Debugger does not work with fastcgi. It works with mongrel and webrick.&lt;/p&gt;</description>
      <pubDate>Sat, 22 Sep 2007 15:40:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:9fd65c2b-6358-4cea-9b23-d95fe01dfdec</guid>
      <author>dapatil@scattrbrain.com (Darshan Patil)</author>
      <link>http://scattrbrain.com/articles/2007/09/22/debugging-rails</link>
      <category>Ruby</category>
      <category>ruby</category>
      <trackback:ping>http://scattrbrain.com/articles/trackback/196</trackback:ping>
    </item>
    <item>
      <title>mysql.rb errors after upgrading ruby</title>
      <description>&lt;p&gt;I just noticed that my rails projects broke after I upgraded ruby on my linux box. Projects   that had gems and rails frozen break. This is because of code in the &lt;span class="caps"&gt;SHA1&lt;/span&gt; class not being backward compatible.&lt;/p&gt;


To quickly fix a broken rails app that shows the following error:
&lt;pre&gt;
vendor/rails/activerecord/lib/active_record/vendor/mysql.rb:551:in `initialize'
&lt;/pre&gt;

	&lt;p&gt;edit the mysql.rb file so that the scramble41 routine looks like:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;scramble41&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;password&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;message&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="number"&gt;0x00&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;chr&lt;/span&gt; &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;password&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;nil?&lt;/span&gt; &lt;span class="keyword"&gt;or&lt;/span&gt; &lt;span class="ident"&gt;password&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;empty?&lt;/span&gt;
    &lt;span class="ident"&gt;buf&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="number"&gt;0x14&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;
    &lt;span class="ident"&gt;s1&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Digest&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;SHA1&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;digest&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;password&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;s2&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Digest&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;SHA1&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;digest&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;s1&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;x&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Digest&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;SHA1&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;digest&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;message&lt;/span&gt; &lt;span class="punct"&gt;+&lt;/span&gt; &lt;span class="ident"&gt;s2&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;0&lt;/span&gt;&lt;span class="punct"&gt;..&lt;/span&gt;&lt;span class="ident"&gt;s1&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;length&lt;/span&gt; &lt;span class="punct"&gt;-&lt;/span&gt; &lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;each&lt;/span&gt; &lt;span class="punct"&gt;{|&lt;/span&gt;&lt;span class="ident"&gt;i&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;buf&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;push&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;s1&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;i&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt; ^ &lt;span class="ident"&gt;x&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;i&lt;/span&gt;&lt;span class="punct"&gt;])}&lt;/span&gt;
    &lt;span class="ident"&gt;buf&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;pack&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;C*&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
      <pubDate>Thu, 09 Aug 2007 01:34:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:3c174c21-b10b-42aa-8b44-d5aa9c45334b</guid>
      <author>dapatil@scattrbrain.com (Darshan Patil)</author>
      <link>http://scattrbrain.com/articles/2007/08/09/mysql-rb-errors-after-upgrading-ruby</link>
      <category>Ruby</category>
      <category>Programming</category>
      <category>ruby</category>
      <category>mysql</category>
      <trackback:ping>http://scattrbrain.com/articles/trackback/186</trackback:ping>
    </item>
    <item>
      <title>Cracking software on the mac</title>
      <description>&lt;p&gt;
Cracking software on the MacOSX is easy. Once you install XCode you pretty much have everything you need to crack software.  Software you need: 
&lt;/p&gt;&lt;p&gt;
gdb - Debugger 
&lt;br /&gt;otool - Disassembler 
&lt;br /&gt;otx - GUI for otool 
&lt;br /&gt;nm - Displays symbols in a binary
&lt;br /&gt;Hex Fiend - Hex editor
&lt;/p&gt;&lt;p&gt;
If you've done any kind of hacking on linux, using gdb should be familiar to you.
&lt;/p&gt;&lt;p&gt;
gdb commands you would use:
&lt;/p&gt;&lt;p&gt;
&lt;strong&gt;set disassembly-flavor intel&lt;/strong&gt;
&lt;br /&gt;This sets the disassembled output to intel syntax from the default att syntax. 
&lt;/p&gt;&lt;p&gt;
&lt;strong&gt;disassemble&lt;/strong&gt; functionname
&lt;br /&gt;This returns the assembly listing for a function
&lt;br /&gt; 
&lt;br /&gt;&lt;strong&gt;stepi&lt;/strong&gt;/&lt;strong&gt;nexti
&lt;br /&gt;&lt;/strong&gt;Step into/next instruction&lt;strong&gt;
&lt;br /&gt;&lt;/strong&gt;
&lt;br /&gt;&lt;strong&gt;info registers
&lt;br /&gt;&lt;/strong&gt;Displays the registers and their contents
&lt;/p&gt;&lt;p&gt;
&lt;strong&gt;x/FMT ADDRESS&lt;/strong&gt;
&lt;br /&gt;Examine memory. Run help x in the gdb for details.
&lt;br /&gt;example: x/10xb 0x989b
&lt;br /&gt;displays 10 bytes in hex starting at 0x989b
&lt;/p&gt;&lt;p&gt;
&lt;strong&gt;break 
&lt;br /&gt;&lt;/strong&gt;Set a breakpoint. Run help break for details
&lt;/p&gt;&lt;p&gt;
&lt;strong&gt;bt/where&lt;/strong&gt;
&lt;br /&gt;Displays the stack trace
&lt;/p&gt;&lt;p&gt;
&lt;strong&gt;up/down&lt;/strong&gt;
&lt;br /&gt;Move up and down the stack frames
&lt;br /&gt; 
&lt;br /&gt;&lt;strong&gt;How to crack ?
&lt;br /&gt;&lt;/strong&gt;Cracking is illegal and you should only be doing this to check how easy it is for someone to crack your application. I could give you step by step instructions on how to crack a commercial application but that would be both illegal and unfair to the app.
&lt;/p&gt;&lt;p&gt;
To crack an application:
&lt;br /&gt;1 - Run nm &amp;#38; otool on the application to get the list of symbols and the disassembled output. You can look at the disassembled output to get a grip on the code flow.
&lt;/p&gt;&lt;p&gt;
2. Run the application under the debugger and set breakpoints in functions you think are interesting. Or better yet, when the registration/unlock screen pops up, hit ctrl-c in the debugger and get a stack trace to find out functions you should be looking at.
&lt;/p&gt;&lt;p&gt;
3. Once you find the function you need to tweak, see the instructions that you need to modify. You NEED to know assembly for this. Once you find the instructions you need to replace, find the machine code equivalent. Once you get the machine code, you can use a hex editor to replace the current instructions with the new ones. This is the basic premise, but there are some caveats to this that you need to know about. Sometimes, you will need to replace x bytes of machine codes with y bytes where x &amp;gt; y. This is the easy case, you can put nop instructions for the unused bytes. Things get considerably harder the other way around. You need to find an equivalent instruction that does the same thing or sometimes rewrite the complete function.
&lt;/p&gt;
&lt;!-- technorati tags start --&gt;&lt;p style="text-align:right;font-size:10px;"&gt;Technorati Tags: &lt;a href="http://www.technorati.com/tag/cracking" rel="tag"&gt;cracking&lt;/a&gt;, &lt;a href="http://www.technorati.com/tag/macosx" rel="tag"&gt;macosx&lt;/a&gt;&lt;/p&gt;&lt;!-- technorati tags end --&gt;</description>
      <pubDate>Sun, 11 Mar 2007 00:57:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:18c178b6-a954-4231-84e2-294f9fc1dd43</guid>
      <author>dapatil@scattrbrain.com (Darshan Patil)</author>
      <link>http://scattrbrain.com/articles/2007/03/11/cracking-software-on-the-mac</link>
      <category>Programming</category>
      <category>Software</category>
      <category>cracking</category>
      <category>programming</category>
      <category>macosx</category>
    </item>
    <item>
      <title>Bit the bullet and bought a MacBook</title>
      <description>&lt;p&gt;
My sister stepped on her laptop a few months ago. So I gave her my old trusty laptop which I had not been using for a while. All 8 lbs of my trusty HP laptop from 2002. It was still a good machine and she is happy with it. 
&lt;/p&gt;&lt;p&gt;
I have a linux box and a windows box setup with dual monitors. I normally use the windows box and use Exceed to connect to the linux box. This setup serves me well. I miss my laptop on days when I want to lie down on my couch, watch TV and do stuff on the computer. So I was in the market for a laptop.
&lt;/p&gt;&lt;p&gt;
I had been eyeing the macbooks for a while. I'm a man. Things that look good attract me :). I also knew that MacOSX has a UNIX core so, it would not be too hard to adapt. The fact that I could install linux/XP on the macbook made my decision a little easier. Anyway long story short, I got a MacBook.
&lt;/p&gt;&lt;p&gt;
I love the hardware. Looks nice, feels nice and just works.  I'm getting used to MacOSX. There are some things which I don't like about it.
&lt;/p&gt;&lt;p&gt;
1. There is no concept of maximize in the mac. I hate having to resize windows manually to use the full screen.
&lt;br /&gt;2. No right click. Ctrl-Click gives you a context menu like the right click on Windows. I guess I would be  a lot more productive on the mac if they had a right click button.
&lt;/p&gt;&lt;p&gt;
Anyway more to explore. But I like what I see. I can drop into the shell and build, install utilities I need, the UI is nice. Most of the apps I need on the go are available.
&lt;/p&gt;&lt;p&gt;
I don't think I could do away with my linux &amp;#38; windows boxes though. I would need them just to develop on those platforms. And there are apps there that I just cannot live without.
&lt;/p&gt;&lt;p&gt;
&lt;a href="http://www.amazon.com/gp/redirect.html%3FASIN=0596510551%26tag=scatterbrainb-20%26lcode=xm2%26cID=2025%26ccmID=165953%26location=/o/ASIN/0596510551%253FSubscriptionId=02ZH6J1W0649DTNS6002"&gt;"Mac OS X Leopard for Starters: The Missing Manual" (David Pogue)&lt;/a&gt;
&lt;/p&gt;</description>
      <pubDate>Thu, 08 Mar 2007 13:48:16 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:66b1f5c0-2a73-4dfb-ba60-1c0dd6733d1b</guid>
      <author>dapatil@scattrbrain.com (Darshan Patil)</author>
      <link>http://scattrbrain.com/articles/2007/03/08/bit-the-bullet-and-bought-a-macbook</link>
      <category>Electronics</category>
      <category>General</category>
    </item>
  </channel>
</rss>
