<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">
 
 <title>Geoff Garside</title>
 
 <link href="http://geoffgarside.co.uk/" rel="alternate" />
 <updated>2010-03-09T09:13:36+00:00</updated>
 <id>http://geoffgarside.co.uk/</id>
 <rights>Copyright (c) 2004 - 2010</rights>
 <author>
   <name>Geoff Garside</name>
   <email>geoff@geoffgarside.co.uk</email>
 </author>
 

 <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/geoffgarside" /><feedburner:info uri="geoffgarside" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry>
   <title>Checking git staged files for tabs before committing</title>
   <link href="http://feedproxy.google.com/~r/geoffgarside/~3/7WHhyYXZu9U/checking-git-staged-files-for-tabs-before-committing" rel="alternate" type="text/html" />
   <updated>2010-01-10T19:42:00+00:00</updated>
   <id>http://geoffgarside.co.uk/2010/01/10/checking-git-staged-files-for-tabs-before-committing</id>
   <content type="html">&lt;p&gt;I recently cocked up a bunch of files in a project I'm working on because I'd inadvertently changed the language indentation from Soft Tabs to Tabs in TextMate. When I finally noticed this I was a might bit annoyed, not least because I'd have to change all the files and thereby nuke half of the &lt;code&gt;git blame&lt;/code&gt; history. The first step of this was to find the files with the tab characters in them, a quick google revealed this&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="nv"&gt;$ TAB&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;\t&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;grep -Hnr &lt;span class="s2"&gt;&amp;quot;$TAB&amp;quot;&lt;/span&gt; *
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;which helped me solve the initial problem. I then decided I'd write a &lt;code&gt;rake&lt;/code&gt; task for my project so I can check for tab indented files in the future more easily. I aimed to make this Ruby 1.8 and Ruby 1.9 friendly and came up with the following function&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="lineno"&gt; 1&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;check_for_tabs_in&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;srcfile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="lineno"&gt; 2&lt;/span&gt;   &lt;span class="n"&gt;line_number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="lineno"&gt; 3&lt;/span&gt;   &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;readlines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;srcfile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="lineno"&gt; 4&lt;/span&gt;     &lt;span class="n"&gt;line_number&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="lineno"&gt; 5&lt;/span&gt;     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="lineno"&gt; 6&lt;/span&gt;       &lt;span class="n"&gt;found&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;srcfile&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;line_number&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="lineno"&gt; 7&lt;/span&gt;     &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="lineno"&gt; 8&lt;/span&gt;   &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="lineno"&gt; 9&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="lineno"&gt;10&lt;/span&gt; 
&lt;span class="lineno"&gt;11&lt;/span&gt; &lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="ss"&gt;:check_tabs&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="lineno"&gt;12&lt;/span&gt;   &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:all&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:source&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:tests&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="lineno"&gt;13&lt;/span&gt;   &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:source&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="lineno"&gt;14&lt;/span&gt;     &lt;span class="no"&gt;Dir&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Source/**/*.[hm]&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;srcfile&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="lineno"&gt;15&lt;/span&gt;      &lt;span class="n"&gt;check_for_tabs_in&lt;/span&gt; &lt;span class="n"&gt;srcfile&lt;/span&gt;
&lt;span class="lineno"&gt;16&lt;/span&gt;     &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="lineno"&gt;17&lt;/span&gt;   &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="lineno"&gt;18&lt;/span&gt;   &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:tests&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="lineno"&gt;19&lt;/span&gt;     &lt;span class="no"&gt;Dir&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Test/Units/*.[hm]&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;srcfile&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="lineno"&gt;20&lt;/span&gt;       &lt;span class="n"&gt;check_for_tabs_in&lt;/span&gt; &lt;span class="n"&gt;srcfile&lt;/span&gt;
&lt;span class="lineno"&gt;21&lt;/span&gt;     &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="lineno"&gt;22&lt;/span&gt;   &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="lineno"&gt;23&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;which left me feeling quite happy, then it struck me. What if git could warn me if I was about to commit files with tabs and let me know what files were affected so I could go and fix them. Well, the code was already there above, but I hardly wanted a git hook to call my rake file, so I rolled the function straight into the hook file. Then to make the error output look better I cached the list of found lines and printed the at the end of the message, the result is this lovely life saving snippet of code.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="lineno"&gt; 1&lt;/span&gt; &lt;span class="c1"&gt;#!/usr/bin/env ruby&lt;/span&gt;
&lt;span class="lineno"&gt; 2&lt;/span&gt; 
&lt;span class="lineno"&gt; 3&lt;/span&gt; &lt;span class="n"&gt;found&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;
&lt;span class="lineno"&gt; 4&lt;/span&gt; &lt;span class="sb"&gt;`git diff --cached --name-only`&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;srcfile&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="lineno"&gt; 5&lt;/span&gt;   &lt;span class="n"&gt;line_number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="lineno"&gt; 6&lt;/span&gt;   &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;readlines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;srcfile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="lineno"&gt; 7&lt;/span&gt;     &lt;span class="n"&gt;line_number&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="lineno"&gt; 8&lt;/span&gt;     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="lineno"&gt; 9&lt;/span&gt;       &lt;span class="n"&gt;found&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;srcfile&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;line_number&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="lineno"&gt;10&lt;/span&gt;     &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="lineno"&gt;11&lt;/span&gt;   &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="lineno"&gt;12&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="lineno"&gt;13&lt;/span&gt; 
&lt;span class="lineno"&gt;14&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;found&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;empty?&lt;/span&gt;
&lt;span class="lineno"&gt;15&lt;/span&gt;   &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Error: Attempt to add file with tab indentation&amp;quot;&lt;/span&gt;
&lt;span class="lineno"&gt;16&lt;/span&gt;   &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="lineno"&gt;17&lt;/span&gt;   &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;This project uses spaces rather than tabs for indendation,&amp;quot;&lt;/span&gt;
&lt;span class="lineno"&gt;18&lt;/span&gt;   &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;please fix the lines of the following files and then re-add&amp;quot;&lt;/span&gt;
&lt;span class="lineno"&gt;19&lt;/span&gt;   &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;the files to the index and re-commit.&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="lineno"&gt;20&lt;/span&gt;   &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;found&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="lineno"&gt;21&lt;/span&gt;   &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="lineno"&gt;22&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="lineno"&gt;23&lt;/span&gt; 
&lt;span class="lineno"&gt;24&lt;/span&gt; &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;feel free to use it yourself.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=7WHhyYXZu9U:vBKgr_6AOyA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=7WHhyYXZu9U:vBKgr_6AOyA:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?i=7WHhyYXZu9U:vBKgr_6AOyA:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=7WHhyYXZu9U:vBKgr_6AOyA:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/geoffgarside/~4/7WHhyYXZu9U" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://geoffgarside.co.uk/2010/01/10/checking-git-staged-files-for-tabs-before-committing</feedburner:origLink></entry>

 <entry>
   <title>Running Stompserver with Daemontools</title>
   <link href="http://feedproxy.google.com/~r/geoffgarside/~3/8l9WVNyhQGY/running-stompserver-with-daemontools" rel="alternate" type="text/html" />
   <updated>2009-10-23T08:57:00+01:00</updated>
   <id>http://geoffgarside.co.uk/2009/10/23/running-stompserver-with-daemontools</id>
   <content type="html">&lt;p&gt;I've been messing around with &lt;a href="http://wiki.opscode.com/display/chef/Home"&gt;chef&lt;/a&gt; recently and needed to setup a &lt;a href="http://stompserver.rubyforge.org/"&gt;stompserver&lt;/a&gt; for the &lt;a href="http://wiki.opscode.com/display/chef/Home"&gt;chef&lt;/a&gt; indexer. As I normally have &lt;a href="http://cr.yp.to/daemontools.html"&gt;daemontools&lt;/a&gt; installed on my servers anyway I thought I'd have a go at running &lt;a href="http://stompserver.rubyforge.org/"&gt;stompserver&lt;/a&gt; under &lt;a href="http://cr.yp.to/daemontools.html"&gt;daemontools&lt;/a&gt; rather than &lt;a href="http://smarden.org/runit/"&gt;runit&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;My instructions will deviate a little from the prescribed &lt;a href="http://cr.yp.to/daemontools.html"&gt;daemontools&lt;/a&gt; configuration. I'm running &lt;a href="http://www.freebsd.org/"&gt;FreeBSD&lt;/a&gt; and using the &lt;code&gt;sysutils/daemontools&lt;/code&gt; port which runs out of &lt;code&gt;/var/service&lt;/code&gt; rather than &lt;code&gt;/service&lt;/code&gt;. This should be the only difference between my instructions and those for a Linux based operating system.&lt;/p&gt;

&lt;p&gt;I'm assuming you've already got &lt;a href="http://cr.yp.to/daemontools.html"&gt;daemontools&lt;/a&gt; installed and that its running.&lt;/p&gt;

&lt;h2&gt;Installing Stompserver&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://stompserver.rubyforge.org/"&gt;Stompserver&lt;/a&gt; is a &lt;a href="http://rubyforge.org/projects/rubygems"&gt;RubyGem&lt;/a&gt; which requires &lt;a href="http://www.ruby-lang.org"&gt;Ruby&lt;/a&gt; and &lt;a href="http://rubyforge.org/projects/rubygems"&gt;RubyGems&lt;/a&gt; to be installed. On &lt;a href="http://www.freebsd.org/"&gt;FreeBSD&lt;/a&gt; the following commands will install Ruby and &lt;a href="http://rubyforge.org/projects/rubygems"&gt;RubyGems&lt;/a&gt;&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="sh"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /usr/ports/lang/ruby18
make install clean
&lt;span class="nb"&gt;cd&lt;/span&gt; /usr/ports/devel/ruby-gems
make install clean
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;or if you've got &lt;code&gt;portupgrade&lt;/code&gt; installed then you'll already have &lt;code&gt;lang/ruby18&lt;/code&gt; so we just need the gems&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="sh"&gt;portinstall devel/ruby-gems
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Now that we've got &lt;a href="http://www.ruby-lang.org"&gt;Ruby&lt;/a&gt; and &lt;a href="http://rubyforge.org/projects/rubygems"&gt;RubyGems&lt;/a&gt; we can install &lt;a href="http://stompserver.rubyforge.org/"&gt;stompserver&lt;/a&gt; with&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="sh"&gt;gem install stompserver --no-ri --no-rdoc
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;I've added the &lt;code&gt;--no-ri --no-rdoc&lt;/code&gt; as I'm going to be running this on a server and don't want the docs as well.&lt;/p&gt;

&lt;h2&gt;Creating the Stompserver directory&lt;/h2&gt;

&lt;p&gt;To begin with we need a place to keep all the &lt;code&gt;run&lt;/code&gt;, &lt;code&gt;env&lt;/code&gt;, &lt;code&gt;log&lt;/code&gt; files and directories which &lt;a href="http://cr.yp.to/daemontools.html"&gt;daemontools&lt;/a&gt; will use to run the server. I've opted for &lt;code&gt;/usr/local/etc/stompserver&lt;/code&gt; and a working directory of &lt;code&gt;/var/db/stompserver&lt;/code&gt;&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="sh"&gt;mkdir -p /usr/local/etc/stompserver
&lt;span class="nb"&gt;cd&lt;/span&gt; /usr/local/etc/stompserver
mkdir -p env log/main
mkdir /var/db/stompserver
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;h2&gt;Creating a user for the stompserver&lt;/h2&gt;

&lt;p&gt;This is short and sweet really, but we'll &lt;code&gt;chown&lt;/code&gt; the folders as well&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="sh"&gt;pw useradd stompserver -d /nonexistent -s /sbin/nologin
chown -R stompserver:stompserver log/main
chown -R stompserver:stompserver /var/db/stompserver
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;h2&gt;The &lt;code&gt;run&lt;/code&gt; scripts&lt;/h2&gt;

&lt;p&gt;Starting off with the multilog &lt;code&gt;run&lt;/code&gt; file&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="sh"&gt;cat &amp;lt; EOF &amp;gt; log/run
&lt;span class="c"&gt;#!/bin/sh&lt;/span&gt;
&lt;span class="nb"&gt;exec &lt;/span&gt;setuidgid stompserver &lt;span class="se"&gt;\&lt;/span&gt;
multilog &lt;span class="se"&gt;\&lt;/span&gt;
    t &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;MAXFILESIZE&lt;/span&gt;&lt;span class="p"&gt;+&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;s$MAXFILESIZE&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;MAXLOGFILES&lt;/span&gt;&lt;span class="p"&gt;+&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;n$MAXLOGFILES&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PROCESSOR&lt;/span&gt;&lt;span class="p"&gt;+&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;!$PROCESSOR&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    ./main
EOF
chmod 755 log/run
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;now for the &lt;a href="http://stompserver.rubyforge.org/"&gt;stompserver&lt;/a&gt; &lt;code&gt;run&lt;/code&gt; file. First lets set some &lt;code&gt;env&lt;/code&gt; variables we'll use in the &lt;code&gt;run&lt;/code&gt; file&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="sh"&gt;&lt;span class="nb"&gt;echo &lt;/span&gt;localhost &amp;gt; env/HOST
&lt;span class="nb"&gt;echo &lt;/span&gt;61613 &amp;gt; env/PORT
&lt;span class="nb"&gt;echo &lt;/span&gt;memory &amp;gt; env/QUEUETYPE
&lt;span class="nb"&gt;echo &lt;/span&gt;0 &amp;gt; env/SECONDS
&lt;span class="nb"&gt;echo&lt;/span&gt; /var/db/stompserver &amp;gt; env/WORKING_DIR
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;and now the &lt;code&gt;run&lt;/code&gt; file&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="sh"&gt;cat &amp;lt; EOF &amp;gt; run
&lt;span class="nb"&gt;exec &lt;/span&gt;2&amp;gt;&amp;amp;1
envdir ./env &lt;span class="se"&gt;\&lt;/span&gt;
sh -c &lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;
&lt;span class="s1"&gt;    exec \&lt;/span&gt;
&lt;span class="s1"&gt;    setuidgid stompserver \&lt;/span&gt;
&lt;span class="s1"&gt;    /usr/local/bin/stompserver \&lt;/span&gt;
&lt;span class="s1"&gt;        ${PORT+&amp;quot;-p$PORT&amp;quot;} ${HOST+&amp;quot;-b$HOST&amp;quot;} \&lt;/span&gt;
&lt;span class="s1"&gt;        ${QUEUETYPE+&amp;quot;-q$QUEUETYPE&amp;quot;} \&lt;/span&gt;
&lt;span class="s1"&gt;        ${WORKING_DIR+&amp;quot;-w$WORKING_DIR&amp;quot;} \&lt;/span&gt;
&lt;span class="s1"&gt;        ${DEBUG+&amp;quot;-d&amp;quot;} \&lt;/span&gt;
&lt;span class="s1"&gt;        ${AUTH+&amp;quot;-a&amp;quot;} \&lt;/span&gt;
&lt;span class="s1"&gt;        ${SECONDS+&amp;quot;-c$SECONDS&amp;quot;}&lt;/span&gt;
&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;
EOF
chmod 755 run
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;its worth noting that if you set either &lt;code&gt;env/DEBUG&lt;/code&gt; or &lt;code&gt;env/AUTH&lt;/code&gt; then debug or auth flags will be set when the stompserver is run.&lt;/p&gt;

&lt;h2&gt;Starting the Stompserver&lt;/h2&gt;

&lt;p&gt;Now it is only required to link the &lt;a href="http://stompserver.rubyforge.org/"&gt;stompserver&lt;/a&gt; directory into the &lt;a href="http://cr.yp.to/daemontools.html"&gt;daemontools&lt;/a&gt; service directory&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="sh"&gt;ln -s /usr/local/etc/stompserver /var/service
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;you can check that its working with&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="sh"&gt;svstat /var/service/stompserver
ps aux | grep stompserver
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;



&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=8l9WVNyhQGY:39Jm66dhP8s:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=8l9WVNyhQGY:39Jm66dhP8s:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?i=8l9WVNyhQGY:39Jm66dhP8s:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=8l9WVNyhQGY:39Jm66dhP8s:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/geoffgarside/~4/8l9WVNyhQGY" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://geoffgarside.co.uk/2009/10/23/running-stompserver-with-daemontools</feedburner:origLink></entry>

 <entry>
   <title>Handling arguments with execve</title>
   <link href="http://feedproxy.google.com/~r/geoffgarside/~3/KIU2y798AkE/handling-arguments-with-execve" rel="alternate" type="text/html" />
   <updated>2009-09-13T11:53:00+01:00</updated>
   <id>http://geoffgarside.co.uk/2009/09/13/handling-arguments-with-execve</id>
   <content type="html">&lt;p&gt;As I mentioned in my &lt;a href="/2009/08/28/using-execve-for-the-first-time"&gt;previous&lt;/a&gt; post I've been working on a project at &lt;a href="http://icecolo.com/"&gt;work&lt;/a&gt; which required me to be managing shell commands from a C program. The solution I documented worked fine so long as you knew all of the arguments at compile time. Another popular requirement would be to generate a command string and have this passed to the external program. Unfortunately this adds some complications.&lt;/p&gt;

&lt;p&gt;Here is the main executing body of our program from last time.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="c"&gt;&lt;span class="lineno"&gt; 1&lt;/span&gt; &lt;span class="n"&gt;pid_t&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="lineno"&gt; 2&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="lineno"&gt; 3&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;envp&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="lineno"&gt; 4&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;./test_args&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;hello&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;there&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="lineno"&gt; 5&lt;/span&gt; 
&lt;span class="lineno"&gt; 6&lt;/span&gt; &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fork&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="lineno"&gt; 7&lt;/span&gt;   &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;:
&lt;span class="lineno"&gt; 8&lt;/span&gt;     &lt;span class="n"&gt;perror&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;fork()&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="lineno"&gt; 9&lt;/span&gt;     &lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EXIT_FAILURE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="lineno"&gt;10&lt;/span&gt;   &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;: &lt;span class="c"&gt;// in the child&lt;/span&gt;
&lt;span class="lineno"&gt;11&lt;/span&gt;     &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;execve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;./test_args&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;envp&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="lineno"&gt;12&lt;/span&gt;     &lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c"&gt;// only happens if execve(2) fails&lt;/span&gt;
&lt;span class="lineno"&gt;13&lt;/span&gt;   &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="c"&gt;// in parent&lt;/span&gt;
&lt;span class="lineno"&gt;14&lt;/span&gt;     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;waitpid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="lineno"&gt;15&lt;/span&gt;       &lt;span class="n"&gt;perror&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;waitpid()&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="lineno"&gt;16&lt;/span&gt;       &lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EXIT_FAILURE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="lineno"&gt;17&lt;/span&gt;     &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="lineno"&gt;18&lt;/span&gt; 
&lt;span class="lineno"&gt;19&lt;/span&gt;     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;WIFEXITED&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="lineno"&gt;20&lt;/span&gt;       &lt;span class="c"&gt;// return status from child, ie ./test_args&lt;/span&gt;
&lt;span class="lineno"&gt;21&lt;/span&gt;       &lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;WEXITSTATUS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="lineno"&gt;22&lt;/span&gt;     &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="lineno"&gt;23&lt;/span&gt;     &lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EXIT_FAILURE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="lineno"&gt;24&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;So say we wanted to throw &lt;code&gt;"hello there world"&lt;/code&gt; as arguments to &lt;code&gt;test_args&lt;/code&gt;. We could changes line 4 to read&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="c"&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;./test_args&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;hello there world&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;and I would forgive you for thinking that test args would get 4 arguments, in fact it only gets 2. The second argument is just the full string. If you look at the line above this is actually fairly obvious.&lt;/p&gt;

&lt;h2&gt;Generating our arguments&lt;/h2&gt;

&lt;p&gt;So in order for this to work we have to preprocess the &lt;code&gt;"hello there world"&lt;/code&gt; string into an &lt;code&gt;argv**&lt;/code&gt; list. Unfortunately its now been a while since I had to do this so I won't be going into great detail as to how the function evolved. So I'll just splat it straight down and then go through it.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="c"&gt;&lt;span class="lineno"&gt; 1&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="nf"&gt;argv_from_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="lineno"&gt; 2&lt;/span&gt;  &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;spaces&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;argc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="lineno"&gt; 3&lt;/span&gt;  &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="lineno"&gt; 4&lt;/span&gt; 
&lt;span class="lineno"&gt; 5&lt;/span&gt;  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="lineno"&gt; 6&lt;/span&gt;      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;isspace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;spaces&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="lineno"&gt; 7&lt;/span&gt; 
&lt;span class="lineno"&gt; 8&lt;/span&gt;  &lt;span class="c"&gt;// add 1 for cmd, 1 for NULL and 1 as spaces will be one short&lt;/span&gt;
&lt;span class="lineno"&gt; 9&lt;/span&gt;  &lt;span class="n"&gt;argv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;malloc&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;spaces&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="lineno"&gt;10&lt;/span&gt;  &lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="lineno"&gt;11&lt;/span&gt;  &lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="lineno"&gt;12&lt;/span&gt; 
&lt;span class="lineno"&gt;13&lt;/span&gt;  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="lineno"&gt;14&lt;/span&gt;      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;isspace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="lineno"&gt;15&lt;/span&gt;          &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sc"&gt;&amp;#39;\0&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="lineno"&gt;16&lt;/span&gt;          &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="lineno"&gt;17&lt;/span&gt;            &lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="lineno"&gt;18&lt;/span&gt;      &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="lineno"&gt;19&lt;/span&gt;  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="lineno"&gt;20&lt;/span&gt; 
&lt;span class="lineno"&gt;21&lt;/span&gt;  &lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="lineno"&gt;22&lt;/span&gt;  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="lineno"&gt;23&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;The algorithm is quite simple, lines 4 and 5 count the number of spaces in the argument string. This tells us how big we need to make the argv list. Once we know how big the argument list is we need to allocate the memory for that list.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt; that whatever function calls this will need to free the memory allocated by it. This is slightly bad form, but I felt it was acceptable in this case.&lt;/p&gt;

&lt;p&gt;Next the arguments are added to the list using the &lt;code&gt;argv[argc++]&lt;/code&gt; lines. On line 10 the first argument is added to the list, over the course of lines 12 to 18 the spaces within the argument string are replaced with null characters to terminate the strings. The starts of the new strings are then added to the argv list. Finally on line 20 the null sentinel is added at the end of the argv list.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt; the &lt;code&gt;char *args&lt;/code&gt; contents are permanently changed by &lt;code&gt;argv_from_string&lt;/code&gt;, if the calling function does not want to alter its argument string it should duplicate it and pass the clone to &lt;code&gt;argv_from_string&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;Using &lt;code&gt;argv_from_string&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;Now I've already alluded to two issues when calling &lt;code&gt;argv_from_string&lt;/code&gt;. The caller needs to ensure its memory is freed and potentially make a clone of the argument string before passing it if it cares about it being modified. So then to use this new function we need to change the main executing body above to&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="c"&gt;&lt;span class="lineno"&gt; 1&lt;/span&gt; &lt;span class="n"&gt;pid_t&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="lineno"&gt; 2&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="lineno"&gt; 3&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="lineno"&gt; 4&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;envp&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="lineno"&gt; 5&lt;/span&gt; 
&lt;span class="lineno"&gt; 6&lt;/span&gt; &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fork&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="lineno"&gt; 7&lt;/span&gt;   &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;:
&lt;span class="lineno"&gt; 8&lt;/span&gt;     &lt;span class="n"&gt;perror&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;fork()&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="lineno"&gt; 9&lt;/span&gt;     &lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EXIT_FAILURE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="lineno"&gt;10&lt;/span&gt;   &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;: &lt;span class="c"&gt;// in the child&lt;/span&gt;
&lt;span class="lineno"&gt;11&lt;/span&gt;     &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;strdup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c"&gt;// cmd is our argument string&lt;/span&gt;
&lt;span class="lineno"&gt;12&lt;/span&gt;     &lt;span class="n"&gt;argv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;argv_from_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;./test_args&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="lineno"&gt;13&lt;/span&gt; 
&lt;span class="lineno"&gt;14&lt;/span&gt;     &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;execve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;./test_args&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;envp&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="lineno"&gt;15&lt;/span&gt; 
&lt;span class="lineno"&gt;16&lt;/span&gt;     &lt;span class="c"&gt;// only happens if execve(2) fails&lt;/span&gt;
&lt;span class="lineno"&gt;17&lt;/span&gt;     &lt;span class="n"&gt;free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="lineno"&gt;18&lt;/span&gt;     &lt;span class="n"&gt;free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;argv&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="lineno"&gt;19&lt;/span&gt;     &lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="lineno"&gt;20&lt;/span&gt;   &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="c"&gt;// in parent&lt;/span&gt;
&lt;span class="lineno"&gt;21&lt;/span&gt;     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;waitpid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="lineno"&gt;22&lt;/span&gt;       &lt;span class="n"&gt;perror&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;waitpid()&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="lineno"&gt;23&lt;/span&gt;       &lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EXIT_FAILURE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="lineno"&gt;24&lt;/span&gt;     &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="lineno"&gt;25&lt;/span&gt; 
&lt;span class="lineno"&gt;26&lt;/span&gt;     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;WIFEXITED&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="lineno"&gt;27&lt;/span&gt;       &lt;span class="c"&gt;// return status from child, ie ./test_args&lt;/span&gt;
&lt;span class="lineno"&gt;28&lt;/span&gt;       &lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;WEXITSTATUS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="lineno"&gt;29&lt;/span&gt;     &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="lineno"&gt;30&lt;/span&gt;     &lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EXIT_FAILURE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="lineno"&gt;31&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;the main body of changes are on lines 3 to 4 and 10 to 20. On lines 3 and 4 we've altered our variable list to include a string called &lt;code&gt;args&lt;/code&gt; and an array of strings called &lt;code&gt;argv&lt;/code&gt;. Now the real work begins on line 10, here we duplicate the string of arguments we received, this is so we don't trample the contents. We then pass this string of arguments to &lt;code&gt;argv_from_string&lt;/code&gt; with the name of the program we are executing.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;execve(2)&lt;/code&gt; call itself hasn't changed, but should it fail we first cleanup the argument list and duplicated arguments string before exiting.&lt;/p&gt;

&lt;p&gt;Now you might wonder why I chose to do all of this in the forked child instead of doing this before calling &lt;code&gt;fork(2)&lt;/code&gt;. My reasoning for this is that the external program I am executing is likely to be short lived and so memory created in its space will be freed by the operating system when its done. Also by keeping all of this in only the child I don't have to worry about freeing the memory in the parent or in the event that &lt;code&gt;fork(2)&lt;/code&gt; fails.&lt;/p&gt;

&lt;p&gt;Well I hope thats been useful for you.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=KIU2y798AkE:zOPtbljuMGI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=KIU2y798AkE:zOPtbljuMGI:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?i=KIU2y798AkE:zOPtbljuMGI:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=KIU2y798AkE:zOPtbljuMGI:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/geoffgarside/~4/KIU2y798AkE" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://geoffgarside.co.uk/2009/09/13/handling-arguments-with-execve</feedburner:origLink></entry>

 <entry>
   <title>XML Demolisher</title>
   <link href="http://feedproxy.google.com/~r/geoffgarside/~3/SHhxBCmU9BI/xml-demolisher" rel="alternate" type="text/html" />
   <updated>2009-08-28T11:25:00+01:00</updated>
   <id>http://geoffgarside.co.uk/2009/08/28/xml-demolisher</id>
   <content type="html">&lt;p&gt;The majority of people familiar with &lt;a href="http://ruby-lang.org/"&gt;Ruby&lt;/a&gt; have at one time or another used the &lt;a href="http://rubyforge.org/projects/builder/"&gt;Builder&lt;/a&gt; library to generate XML files. &lt;a href="http://rubyforge.org/projects/builder/"&gt;Builder&lt;/a&gt; is nice in that it provides a very ruby-ish interface to writing XML.&lt;/p&gt;

&lt;p&gt;For example the following &lt;a href="http://rubyforge.org/projects/builder/"&gt;Builder&lt;/a&gt; code&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="lineno"&gt; 1&lt;/span&gt; &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;builder&amp;#39;&lt;/span&gt;
&lt;span class="lineno"&gt; 2&lt;/span&gt; 
&lt;span class="lineno"&gt; 3&lt;/span&gt; &lt;span class="n"&gt;people&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;
&lt;span class="lineno"&gt; 4&lt;/span&gt;   &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;:firstname&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Enoch&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:lastname&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Root&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="lineno"&gt; 5&lt;/span&gt;     &lt;span class="ss"&gt;:phone&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;01234 567 8900&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:email&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;enoch@example.com&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="lineno"&gt; 6&lt;/span&gt;     &lt;span class="ss"&gt;:active&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="lineno"&gt; 7&lt;/span&gt;   &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;:firstname&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Randy&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:lastname&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Waterhouse&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="lineno"&gt; 8&lt;/span&gt;     &lt;span class="ss"&gt;:phone&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;01234 567 8901&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:email&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;randy@example.com&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="lineno"&gt; 9&lt;/span&gt;     &lt;span class="ss"&gt;:active&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="lineno"&gt;10&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="lineno"&gt;11&lt;/span&gt; 
&lt;span class="lineno"&gt;12&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;addressbook.xml&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;w&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="lineno"&gt;13&lt;/span&gt;   &lt;span class="n"&gt;xml&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Builder&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;XmlMarkup&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:target&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:indent&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="lineno"&gt;14&lt;/span&gt;   &lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;instruct!&lt;/span&gt;
&lt;span class="lineno"&gt;15&lt;/span&gt;   
&lt;span class="lineno"&gt;16&lt;/span&gt;   &lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addressbook&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="lineno"&gt;17&lt;/span&gt;     &lt;span class="n"&gt;people&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;person&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="lineno"&gt;18&lt;/span&gt;       &lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;person&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="lineno"&gt;19&lt;/span&gt;         &lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;firstname&lt;/span&gt; &lt;span class="n"&gt;person&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:firstname&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="lineno"&gt;20&lt;/span&gt;         &lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lastname&lt;/span&gt;  &lt;span class="n"&gt;person&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:lastname&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="lineno"&gt;21&lt;/span&gt;         &lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;contact&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="lineno"&gt;22&lt;/span&gt;           &lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;phone&lt;/span&gt; &lt;span class="n"&gt;person&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:phone&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="lineno"&gt;23&lt;/span&gt;           &lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="n"&gt;person&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:email&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="lineno"&gt;24&lt;/span&gt;         &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="lineno"&gt;25&lt;/span&gt;         &lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt; &lt;span class="n"&gt;person&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:active&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;YES&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;NO&amp;#39;&lt;/span&gt;
&lt;span class="lineno"&gt;26&lt;/span&gt;       &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="lineno"&gt;27&lt;/span&gt;     &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="lineno"&gt;28&lt;/span&gt;   &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="lineno"&gt;29&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;will generate this XML&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="xml"&gt;&lt;span class="lineno"&gt; 1&lt;/span&gt; &lt;span class="cp"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;/span&gt;
&lt;span class="lineno"&gt; 2&lt;/span&gt; &lt;span class="nt"&gt;&amp;lt;addressbook&amp;gt;&lt;/span&gt;
&lt;span class="lineno"&gt; 3&lt;/span&gt;   &lt;span class="nt"&gt;&amp;lt;person&amp;gt;&lt;/span&gt;
&lt;span class="lineno"&gt; 4&lt;/span&gt;     &lt;span class="nt"&gt;&amp;lt;firstname&amp;gt;&lt;/span&gt;Enoch&lt;span class="nt"&gt;&amp;lt;/firstname&amp;gt;&lt;/span&gt;
&lt;span class="lineno"&gt; 5&lt;/span&gt;     &lt;span class="nt"&gt;&amp;lt;lastname&amp;gt;&lt;/span&gt;Root&lt;span class="nt"&gt;&amp;lt;/lastname&amp;gt;&lt;/span&gt;
&lt;span class="lineno"&gt; 6&lt;/span&gt;     &lt;span class="nt"&gt;&amp;lt;contact&amp;gt;&lt;/span&gt;
&lt;span class="lineno"&gt; 7&lt;/span&gt;       &lt;span class="nt"&gt;&amp;lt;phone&amp;gt;&lt;/span&gt;01234 567 8900&lt;span class="nt"&gt;&amp;lt;/phone&amp;gt;&lt;/span&gt;
&lt;span class="lineno"&gt; 8&lt;/span&gt;       &lt;span class="nt"&gt;&amp;lt;email&amp;gt;&lt;/span&gt;enoch@example.com&lt;span class="nt"&gt;&amp;lt;/email&amp;gt;&lt;/span&gt;
&lt;span class="lineno"&gt; 9&lt;/span&gt;     &lt;span class="nt"&gt;&amp;lt;/contact&amp;gt;&lt;/span&gt;
&lt;span class="lineno"&gt;10&lt;/span&gt;     &lt;span class="nt"&gt;&amp;lt;active&amp;gt;&lt;/span&gt;YES&lt;span class="nt"&gt;&amp;lt;/active&amp;gt;&lt;/span&gt;
&lt;span class="lineno"&gt;11&lt;/span&gt;   &lt;span class="nt"&gt;&amp;lt;/person&amp;gt;&lt;/span&gt;
&lt;span class="lineno"&gt;12&lt;/span&gt;   &lt;span class="nt"&gt;&amp;lt;person&amp;gt;&lt;/span&gt;
&lt;span class="lineno"&gt;13&lt;/span&gt;     &lt;span class="nt"&gt;&amp;lt;firstname&amp;gt;&lt;/span&gt;Randy&lt;span class="nt"&gt;&amp;lt;/firstname&amp;gt;&lt;/span&gt;
&lt;span class="lineno"&gt;14&lt;/span&gt;     &lt;span class="nt"&gt;&amp;lt;lastname&amp;gt;&lt;/span&gt;Waterhouse&lt;span class="nt"&gt;&amp;lt;/lastname&amp;gt;&lt;/span&gt;
&lt;span class="lineno"&gt;15&lt;/span&gt;     &lt;span class="nt"&gt;&amp;lt;contact&amp;gt;&lt;/span&gt;
&lt;span class="lineno"&gt;16&lt;/span&gt;       &lt;span class="nt"&gt;&amp;lt;phone&amp;gt;&lt;/span&gt;01234 567 8901&lt;span class="nt"&gt;&amp;lt;/phone&amp;gt;&lt;/span&gt;
&lt;span class="lineno"&gt;17&lt;/span&gt;       &lt;span class="nt"&gt;&amp;lt;email&amp;gt;&lt;/span&gt;randy@example.com&lt;span class="nt"&gt;&amp;lt;/email&amp;gt;&lt;/span&gt;
&lt;span class="lineno"&gt;18&lt;/span&gt;     &lt;span class="nt"&gt;&amp;lt;/contact&amp;gt;&lt;/span&gt;
&lt;span class="lineno"&gt;19&lt;/span&gt;     &lt;span class="nt"&gt;&amp;lt;active&amp;gt;&lt;/span&gt;NO&lt;span class="nt"&gt;&amp;lt;/active&amp;gt;&lt;/span&gt;
&lt;span class="lineno"&gt;20&lt;/span&gt;   &lt;span class="nt"&gt;&amp;lt;/person&amp;gt;&lt;/span&gt;
&lt;span class="lineno"&gt;21&lt;/span&gt; &lt;span class="nt"&gt;&amp;lt;/addressbook&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;nice and easy huh, despite me complicating it by using an array of people in the ruby code you can see how the XML is being put together. Now with the likes of &lt;a href="http://www.ruby-doc.org/stdlib/libdoc/rexml/rdoc/index.html"&gt;REXML&lt;/a&gt; and &lt;a href="http://github.com/whymirror/hpricot/tree/master"&gt;Hpricot&lt;/a&gt; you can, with out a great deal of effort, extract pieces of this XML file back out and re-create the original array. The trouble is that neither of these projects are that well designed for this kind of process as I discovered.&lt;/p&gt;

&lt;p&gt;What I was needing to do was export vast amounts of data into a portable format and then either import it back into the same system or potentially another system. Unfortunately coping with differences between how some other system might want to store that data was very tricky with the normal pick and choose method XML parsing. What I really wanted was something like &lt;a href="http://rubyforge.org/projects/builder/"&gt;Builder&lt;/a&gt; but the other way round. This was actually a lot simpler to achieve than I thought and with only a couple of hours work I had some code do just that.&lt;/p&gt;

&lt;h2&gt;Demolisher&lt;/h2&gt;

&lt;p&gt;So &lt;a href="http://rubyforge.org/projects/demolisher/"&gt;Demolisher&lt;/a&gt; was born, first onto &lt;a href="http://github.com/geoffgarside/demolisher/"&gt;GitHub&lt;/a&gt; and then properly, after adding tests, to &lt;a href="http://rubyforge.org/projects/demolisher/"&gt;Rubyforge&lt;/a&gt;. So to proceed with our addressbook example a bit more, how would you get the information back out?&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="lineno"&gt; 1&lt;/span&gt; &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;demolisher&amp;#39;&lt;/span&gt;
&lt;span class="lineno"&gt; 2&lt;/span&gt; &lt;span class="n"&gt;people&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;
&lt;span class="lineno"&gt; 3&lt;/span&gt; 
&lt;span class="lineno"&gt; 4&lt;/span&gt; &lt;span class="n"&gt;xml&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Demolisher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;demolish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;addressbook.xml&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="lineno"&gt; 5&lt;/span&gt; &lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addressbook&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="lineno"&gt; 6&lt;/span&gt;   &lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;person&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="lineno"&gt; 7&lt;/span&gt;     &lt;span class="n"&gt;person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="lineno"&gt; 8&lt;/span&gt; 
&lt;span class="lineno"&gt; 9&lt;/span&gt;     &lt;span class="n"&gt;person&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:firstname&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;firstname&lt;/span&gt;
&lt;span class="lineno"&gt;10&lt;/span&gt;     &lt;span class="n"&gt;person&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:lastname&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lastname&lt;/span&gt;
&lt;span class="lineno"&gt;11&lt;/span&gt;     &lt;span class="n"&gt;person&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:active&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;active?&lt;/span&gt;
&lt;span class="lineno"&gt;12&lt;/span&gt;     &lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;contact&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="lineno"&gt;13&lt;/span&gt;       &lt;span class="n"&gt;person&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:phone&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;phone&lt;/span&gt;
&lt;span class="lineno"&gt;14&lt;/span&gt;       &lt;span class="n"&gt;person&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:email&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;
&lt;span class="lineno"&gt;15&lt;/span&gt;     &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="lineno"&gt;16&lt;/span&gt; 
&lt;span class="lineno"&gt;17&lt;/span&gt;     &lt;span class="n"&gt;people&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;person&lt;/span&gt;
&lt;span class="lineno"&gt;18&lt;/span&gt;   &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="lineno"&gt;19&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;notice the &lt;code&gt;active?&lt;/code&gt; call, if you append a &lt;code&gt;?&lt;/code&gt; to the end of an element name then it will return true provided the contents of the element are "t", "y", "true", "yes" or 1. This is case insensitive.&lt;/p&gt;

&lt;p&gt;As I found it common in my import/export code to have little wrapped elements for logical grouping like the &lt;code&gt;contact&lt;/code&gt; element above I also added a shorthand approach to accessing sub elements. You can get the contact phone using &lt;code&gt;xml.contact.phone&lt;/code&gt; as well as the block method, so it could also be written as (lines 11 and 12)&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="lineno"&gt; 1&lt;/span&gt; &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;demolisher&amp;#39;&lt;/span&gt;
&lt;span class="lineno"&gt; 2&lt;/span&gt; &lt;span class="n"&gt;people&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;
&lt;span class="lineno"&gt; 3&lt;/span&gt; 
&lt;span class="lineno"&gt; 4&lt;/span&gt; &lt;span class="n"&gt;xml&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Demolisher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;demolish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;addressbook.xml&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="lineno"&gt; 5&lt;/span&gt; &lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addressbook&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="lineno"&gt; 6&lt;/span&gt;   &lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;person&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="lineno"&gt; 7&lt;/span&gt;     &lt;span class="n"&gt;person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="lineno"&gt; 8&lt;/span&gt; 
&lt;span class="lineno"&gt; 9&lt;/span&gt;     &lt;span class="n"&gt;person&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:firstname&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;firstname&lt;/span&gt;
&lt;span class="lineno"&gt;10&lt;/span&gt;     &lt;span class="n"&gt;person&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:lastname&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lastname&lt;/span&gt;
&lt;span class="lineno"&gt;11&lt;/span&gt;     &lt;span class="n"&gt;person&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:phone&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;contact&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;phone&lt;/span&gt;
&lt;span class="lineno"&gt;12&lt;/span&gt;     &lt;span class="n"&gt;person&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:email&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;contact&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;
&lt;span class="lineno"&gt;13&lt;/span&gt;     &lt;span class="n"&gt;person&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:active&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;active?&lt;/span&gt;
&lt;span class="lineno"&gt;14&lt;/span&gt; 
&lt;span class="lineno"&gt;15&lt;/span&gt;     &lt;span class="n"&gt;people&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;person&lt;/span&gt;
&lt;span class="lineno"&gt;16&lt;/span&gt;   &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="lineno"&gt;17&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;I hope you like it and have some more fun demolishing XML data files. You can view the &lt;a href="http://rdoc.info/projects/geoffgarside/demolisher"&gt;rdoc&lt;/a&gt; for only the tiniest bit more information, hey I told you it was pretty simple.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=SHhxBCmU9BI:kDyf7O-tBFI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=SHhxBCmU9BI:kDyf7O-tBFI:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?i=SHhxBCmU9BI:kDyf7O-tBFI:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=SHhxBCmU9BI:kDyf7O-tBFI:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/geoffgarside/~4/SHhxBCmU9BI" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://geoffgarside.co.uk/2009/08/28/xml-demolisher</feedburner:origLink></entry>

 <entry>
   <title>Using execve for the first time</title>
   <link href="http://feedproxy.google.com/~r/geoffgarside/~3/NbtpUs1vP6k/using-execve-for-the-first-time" rel="alternate" type="text/html" />
   <updated>2009-08-28T00:20:00+01:00</updated>
   <id>http://geoffgarside.co.uk/2009/08/28/using-execve-for-the-first-time</id>
   <content type="html">&lt;p&gt;Recently I've been working on a project at &lt;a href="http://icecolo.com/" title="Ice Colo: Premium Data Centre Services"&gt;work&lt;/a&gt; which required me to be managing shell commands from a C program. It's quite an interesting project, when its ready I hope to do a bit of a post on it. I've got quite a limited history of C experience but I do quite enjoy working with the language. Nowhere in my past experience with it had I ever been invoking other programs within my code, so this was definitely a learning experience for me.&lt;/p&gt;

&lt;p&gt;For the purposes of any examples here is the source for the program I will be invoking as &lt;code&gt;test_args&lt;/code&gt;&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="c"&gt;&lt;span class="lineno"&gt; 1&lt;/span&gt; &lt;span class="cp"&gt;#include &amp;lt;stdio.h&amp;gt;&lt;/span&gt;
&lt;span class="lineno"&gt; 2&lt;/span&gt; 
&lt;span class="lineno"&gt; 3&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="lineno"&gt; 4&lt;/span&gt;  &lt;span class="kt"&gt;FILE&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="lineno"&gt; 5&lt;/span&gt;  &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="lineno"&gt; 6&lt;/span&gt; 
&lt;span class="lineno"&gt; 7&lt;/span&gt;  &lt;span class="n"&gt;log&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;./out.txt&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;a+&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c"&gt;// assume it worked&lt;/span&gt;
&lt;span class="lineno"&gt; 8&lt;/span&gt;  &lt;span class="n"&gt;fprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Called with %d args as: &amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="lineno"&gt; 9&lt;/span&gt;  
&lt;span class="lineno"&gt;10&lt;/span&gt;  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;argc&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="lineno"&gt;11&lt;/span&gt;      &lt;span class="n"&gt;fprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="lineno"&gt;12&lt;/span&gt;      &lt;span class="n"&gt;fprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="lineno"&gt;13&lt;/span&gt;      &lt;span class="n"&gt;fprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="lineno"&gt;14&lt;/span&gt;      &lt;span class="n"&gt;fprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot; &amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="lineno"&gt;15&lt;/span&gt;  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="lineno"&gt;16&lt;/span&gt; 
&lt;span class="lineno"&gt;17&lt;/span&gt;  &lt;span class="n"&gt;fprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="lineno"&gt;18&lt;/span&gt; 
&lt;span class="lineno"&gt;19&lt;/span&gt;  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="lineno"&gt;20&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;I've opted to write the arguments passed to the program to a text file for the sake of simplicity.&lt;/p&gt;

&lt;h2&gt;execve(2) and friends&lt;/h2&gt;

&lt;p&gt;The main system call to invoke an external program within your code is &lt;code&gt;execve(2)&lt;/code&gt;. Now that I've said that I'm going to retract nearly all of it. From the manpage&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;execve() transforms the calling process into a new process.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;we see something a bit different, and initially for me a source of confusion. To begin with I was simply calling &lt;code&gt;execve(2)&lt;/code&gt; in my code and letting it do its thing. This is not correct as any veteran of &lt;code&gt;execve(2)&lt;/code&gt; knows and will probably baulk at my stupidity for not &lt;em&gt;getting&lt;/em&gt; it right away.&lt;/p&gt;

&lt;p&gt;So what does the manpage mean in this case, well as I found out to my cost, it means exactly what it says. The moment &lt;code&gt;execve(2)&lt;/code&gt; is entered, provided it doesn't encounter an error, your program becomes the program invoked by &lt;code&gt;execve(2)&lt;/code&gt;. It will run to the end of that invoked program and return you whatever that program would if you'd run it yourself. This was my first tripping point and I quickly found out that I needed to &lt;code&gt;fork(2)&lt;/code&gt; my way around it. As an example, most definitely not to be followed, here is what I had started with&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="c"&gt;&lt;span class="lineno"&gt;1&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="lineno"&gt;2&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;envp&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="lineno"&gt;3&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;./test_args&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;hello&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;there&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="lineno"&gt;4&lt;/span&gt; 
&lt;span class="lineno"&gt;5&lt;/span&gt; &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;execve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;./test_args&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;envp&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="lineno"&gt;6&lt;/span&gt; 
&lt;span class="lineno"&gt;7&lt;/span&gt; &lt;span class="c"&gt;// do things based on ret from test_args down here&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;as I've described, with the exception of an error, nothing after the &lt;code&gt;execve(2)&lt;/code&gt; would be run.&lt;/p&gt;

&lt;p&gt;Now I mentioned friends, &lt;code&gt;execve(2)&lt;/code&gt; is wrapped by a number of functions such as &lt;code&gt;execl&lt;/code&gt;, &lt;code&gt;execle&lt;/code&gt;, &lt;code&gt;execlp&lt;/code&gt;, &lt;code&gt;execv&lt;/code&gt;, &lt;code&gt;execvp&lt;/code&gt; and &lt;code&gt;execvP&lt;/code&gt; which are documented in &lt;code&gt;exec(3)&lt;/code&gt;. These functions primarily offer a selection of different ways to wrap up the call to &lt;code&gt;execve(2)&lt;/code&gt; for your convenience. I won't touch on these again as you can look into them yourself.&lt;/p&gt;

&lt;p&gt;Another friend of &lt;code&gt;execve(2)&lt;/code&gt; is &lt;code&gt;system(2)&lt;/code&gt;, this function takes a command string and passes it to &lt;code&gt;sh(1)&lt;/code&gt; the default shell for interpretation and execution. For small commands it can be a quick way of getting things done but for my needs I didn't feel like it gave me enough control.&lt;/p&gt;

&lt;h2&gt;fork(2)ing around to keep in your program&lt;/h2&gt;

&lt;p&gt;So I needed to first &lt;code&gt;fork(2)&lt;/code&gt; my program before calling &lt;code&gt;execve(2)&lt;/code&gt; to invoke the external program. Now the important thing to remember about &lt;code&gt;fork(2)&lt;/code&gt; is that your program branches into a child and parent. The parent is your controlling process and the child is what you will offer up to the gods of &lt;code&gt;execve(2)&lt;/code&gt; to be transformed into the program you wish to invoke.&lt;/p&gt;

&lt;p&gt;Here follows a crude example...&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="c"&gt;&lt;span class="lineno"&gt; 1&lt;/span&gt; &lt;span class="n"&gt;pid_t&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="lineno"&gt; 2&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="lineno"&gt; 3&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;envp&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="lineno"&gt; 4&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;./test_args&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;hello&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;there&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="lineno"&gt; 5&lt;/span&gt; 
&lt;span class="lineno"&gt; 6&lt;/span&gt; &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fork&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="lineno"&gt; 7&lt;/span&gt;   &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;:
&lt;span class="lineno"&gt; 8&lt;/span&gt;     &lt;span class="n"&gt;perror&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;fork()&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="lineno"&gt; 9&lt;/span&gt;     &lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EXIT_FAILURE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="lineno"&gt;10&lt;/span&gt;   &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;: &lt;span class="c"&gt;// in the child&lt;/span&gt;
&lt;span class="lineno"&gt;11&lt;/span&gt;     &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;execve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;./test_args&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;envp&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="lineno"&gt;12&lt;/span&gt;     &lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c"&gt;// only happens if execve(2) fails&lt;/span&gt;
&lt;span class="lineno"&gt;13&lt;/span&gt;   &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="c"&gt;// in parent&lt;/span&gt;
&lt;span class="lineno"&gt;14&lt;/span&gt;     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;waitpid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="lineno"&gt;15&lt;/span&gt;       &lt;span class="n"&gt;perror&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;waitpid()&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="lineno"&gt;16&lt;/span&gt;       &lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EXIT_FAILURE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="lineno"&gt;17&lt;/span&gt;     &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="lineno"&gt;18&lt;/span&gt; 
&lt;span class="lineno"&gt;19&lt;/span&gt;     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;WIFEXITED&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="lineno"&gt;20&lt;/span&gt;       &lt;span class="c"&gt;// return status from child, ie ./test_args&lt;/span&gt;
&lt;span class="lineno"&gt;21&lt;/span&gt;       &lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;WEXITSTATUS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="lineno"&gt;22&lt;/span&gt;     &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="lineno"&gt;23&lt;/span&gt;     &lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EXIT_FAILURE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="lineno"&gt;24&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;So again we setup the &lt;code&gt;envp&lt;/code&gt; and &lt;code&gt;argv&lt;/code&gt; string arrays to pass to &lt;code&gt;execve(2)&lt;/code&gt; but before that we declare a variable of type &lt;code&gt;pid_t&lt;/code&gt;. This is a type to store Process Identifiers, PIDs, which are returned from &lt;code&gt;fork(2)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I've opted for a &lt;code&gt;switch&lt;/code&gt; statement here, you could equally use an &lt;code&gt;if&lt;/code&gt; but I prefer the readability and clarity of the &lt;code&gt;switch&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So we fork our process and save the returned PID value as we'll need this in the parent. If our PID has a value of &lt;code&gt;-1&lt;/code&gt; then &lt;code&gt;fork(2)&lt;/code&gt; has failed. Now we have the fun part, the child will always get a &lt;code&gt;0&lt;/code&gt; return value from &lt;code&gt;fork(2)&lt;/code&gt;, if you want the PID in the child you can call &lt;code&gt;getpid(2)&lt;/code&gt;. So inside the child we make the call to &lt;code&gt;execve(2)&lt;/code&gt; and capture the result of the call in the event of an error. From this point on the child is &lt;code&gt;test_args&lt;/code&gt; and not our main program. Now the &lt;code&gt;fork(2)&lt;/code&gt; call will return the value of the PID for the child to the parent, so we can catch this with the &lt;code&gt;default&lt;/code&gt; case. In this rather simple example we wait for the child process to complete with &lt;code&gt;waitpid(2)&lt;/code&gt; which will fill in our &lt;code&gt;status&lt;/code&gt; variable with the return value of the child. Next we check the &lt;code&gt;status&lt;/code&gt; to ensure the child exited and didn't crash or die, we then return the status code or indicate failure.&lt;/p&gt;

&lt;p&gt;Thats the basic gist of using &lt;code&gt;execve(2)&lt;/code&gt; to invoke external programs in your code. In a later post I'll describe how I went about handling more free form argument lists.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=NbtpUs1vP6k:NVIHLLa_Df0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=NbtpUs1vP6k:NVIHLLa_Df0:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?i=NbtpUs1vP6k:NVIHLLa_Df0:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=NbtpUs1vP6k:NVIHLLa_Df0:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/geoffgarside/~4/NbtpUs1vP6k" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://geoffgarside.co.uk/2009/08/28/using-execve-for-the-first-time</feedburner:origLink></entry>

 <entry>
   <title>I'm Expert Staff apparently</title>
   <link href="http://feedproxy.google.com/~r/geoffgarside/~3/UXhp-esnJHU/i-m-expert-staff-apparently" rel="alternate" type="text/html" />
   <updated>2009-08-27T23:06:00+01:00</updated>
   <id>http://geoffgarside.co.uk/2009/08/27/i-m-expert-staff-apparently</id>
   <content type="html">&lt;p&gt;Rather recently the &lt;a href="http://openhosting.co.uk/"&gt;company&lt;/a&gt; I work for went through a bit of a re-branding and structural reorganisation. So now &lt;a href="http://openhosting.co.uk/"&gt;Open Hosting&lt;/a&gt; is a &lt;em&gt;division&lt;/em&gt; of a new parent company &lt;em&gt;M247 Ltd&lt;/em&gt;. Part of this re-branding was the creation of a couple of new divisions, one of which is &lt;a href="http://icecolo.com/"&gt;Ice Colo&lt;/a&gt; through which our data centre services are being sold.&lt;/p&gt;

&lt;p&gt;Now a while ago I'd rather foolishly agreed to allow myself to be photographed as part of some generic PR effort, this resulted in the following image&lt;/p&gt;

&lt;p&gt;&lt;a href="/images/posts/icecolo-pr-geoff.jpg"&gt;&lt;img src="/images/posts/icecolo-pr-geoff-thumb.jpg" alt="Geoff IceColo PR Image" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;which was at least not quite as bemusing as&lt;/p&gt;

&lt;p&gt;&lt;a href="/images/posts/icecolo-pr-chris.jpg"&gt;&lt;img src="/images/posts/icecolo-pr-chris-thumb.jpg" alt="Chris IceColo PR Image" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;which I think is fantastic and cheesy at the same time.&lt;/p&gt;

&lt;p&gt;Anyway I digress, the first picture found its way into I believe &lt;em&gt;Data Centre Management&lt;/em&gt; magazine as part of a piece on the data centre we've &lt;a href="http://build.manchesterdc.com/"&gt;built&lt;/a&gt; in Manchester.&lt;/p&gt;

&lt;h3&gt;Expert staff&lt;/h3&gt;

&lt;p&gt;With the creation of the &lt;a href="http://icecolo.com/"&gt;Ice Colo&lt;/a&gt; brand came the inevitable website where once again you can see the image of my lovely self as part of the auto scrolling schpiel under &lt;em&gt;Expert Staff&lt;/em&gt;. Wonderful eh, guess I've now got a reputation to live up to.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=UXhp-esnJHU:loVoRQEBX-k:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=UXhp-esnJHU:loVoRQEBX-k:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?i=UXhp-esnJHU:loVoRQEBX-k:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=UXhp-esnJHU:loVoRQEBX-k:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/geoffgarside/~4/UXhp-esnJHU" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://geoffgarside.co.uk/2009/08/27/i-m-expert-staff-apparently</feedburner:origLink></entry>

 <entry>
   <title>Marketing Idea for Apple</title>
   <link href="http://feedproxy.google.com/~r/geoffgarside/~3/32HjKMR6vk8/marketing-idea-for-apple" rel="alternate" type="text/html" />
   <updated>2009-08-27T22:28:00+01:00</updated>
   <id>http://geoffgarside.co.uk/2009/08/27/marketing-idea-for-apple</id>
   <content type="html">&lt;p&gt;Portrait style banner, fresh green apple at the bottom with a bite taken out of it. Text reads&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;They're just better for you ;)&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;as added bonus, have people standing outside Microsoft stores selling bushels of apples.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=32HjKMR6vk8:AmjX0MKdt70:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=32HjKMR6vk8:AmjX0MKdt70:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?i=32HjKMR6vk8:AmjX0MKdt70:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=32HjKMR6vk8:AmjX0MKdt70:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/geoffgarside/~4/32HjKMR6vk8" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://geoffgarside.co.uk/2009/08/27/marketing-idea-for-apple</feedburner:origLink></entry>

 <entry>
   <title>RSpec with MacRuby, part 2</title>
   <link href="http://feedproxy.google.com/~r/geoffgarside/~3/XAHrpd9VKcQ/rspec-with-macruby-part-2" rel="alternate" type="text/html" />
   <updated>2009-07-24T16:35:00+01:00</updated>
   <id>http://geoffgarside.co.uk/2009/07/24/rspec-with-macruby-part-2</id>
   <content type="html">&lt;p&gt;&lt;a href="http://www.comprovisation.com/news/show/69"&gt;RSpec with MacRuby, part 2&lt;/a&gt;&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=XAHrpd9VKcQ:4ZSuwM5da4w:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=XAHrpd9VKcQ:4ZSuwM5da4w:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?i=XAHrpd9VKcQ:4ZSuwM5da4w:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=XAHrpd9VKcQ:4ZSuwM5da4w:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/geoffgarside/~4/XAHrpd9VKcQ" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://geoffgarside.co.uk/2009/07/24/rspec-with-macruby-part-2</feedburner:origLink></entry>

 <entry>
   <title>RSpec with MacRuby, part 1</title>
   <link href="http://feedproxy.google.com/~r/geoffgarside/~3/qk8HJH_wiHM/rspec-with-macruby-part-1" rel="alternate" type="text/html" />
   <updated>2009-07-24T16:35:00+01:00</updated>
   <id>http://geoffgarside.co.uk/2009/07/24/rspec-with-macruby-part-1</id>
   <content type="html">&lt;p&gt;&lt;a href="http://www.comprovisation.com/news/show/68"&gt;RSpec with MacRuby, part 1&lt;/a&gt;&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=qk8HJH_wiHM:jTLWup4H5Qo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=qk8HJH_wiHM:jTLWup4H5Qo:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?i=qk8HJH_wiHM:jTLWup4H5Qo:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=qk8HJH_wiHM:jTLWup4H5Qo:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/geoffgarside/~4/qk8HJH_wiHM" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://geoffgarside.co.uk/2009/07/24/rspec-with-macruby-part-1</feedburner:origLink></entry>

 <entry>
   <title>Failure in the GPS</title>
   <link href="http://feedproxy.google.com/~r/geoffgarside/~3/CD301UBAOmk/failure-in-the-gps" rel="alternate" type="text/html" />
   <updated>2009-05-26T14:36:00+01:00</updated>
   <id>http://geoffgarside.co.uk/2009/05/26/failure-in-the-gps</id>
   <content type="html">&lt;blockquote&gt;&lt;p&gt;I swear, sometimes it's as if Hollywood sets out with "failure" plugged right into the GPS.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="http://popwatch.ew.com/popwatch/2009/05/new-buffy-movie.html"&gt;A Joss Whedon-less 'Buffy' movie: Worst idea ever of the year&lt;/a&gt;&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=CD301UBAOmk:4NpBSKYgXdE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=CD301UBAOmk:4NpBSKYgXdE:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?i=CD301UBAOmk:4NpBSKYgXdE:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=CD301UBAOmk:4NpBSKYgXdE:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/geoffgarside/~4/CD301UBAOmk" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://geoffgarside.co.uk/2009/05/26/failure-in-the-gps</feedburner:origLink></entry>

 <entry>
   <title>Harsh highlighting</title>
   <link href="http://feedproxy.google.com/~r/geoffgarside/~3/0zfLb60rVF4/harsh-highlighting" rel="alternate" type="text/html" />
   <updated>2009-04-02T13:23:00+01:00</updated>
   <id>http://geoffgarside.co.uk/2009/04/02/harsh-highlighting</id>
   <content type="html">&lt;p&gt;Just read about the &lt;a href="http://carboni.ca/projects/harsh/"&gt;Harsh&lt;/a&gt; ERb/HAML highlighter, it looks quite cool. Also because it uses UltraViolet it can be powered by my version of the &lt;a href="http://github.com/geoffgarside/oniguruma/tree/master"&gt;Oniguruma&lt;/a&gt; gem.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=0zfLb60rVF4:LiiYsLc3JL4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=0zfLb60rVF4:LiiYsLc3JL4:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?i=0zfLb60rVF4:LiiYsLc3JL4:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=0zfLb60rVF4:LiiYsLc3JL4:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/geoffgarside/~4/0zfLb60rVF4" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://geoffgarside.co.uk/2009/04/02/harsh-highlighting</feedburner:origLink></entry>

 <entry>
   <title>Initialising Cocoa NSValueTransformers</title>
   <link href="http://feedproxy.google.com/~r/geoffgarside/~3/rA3Twlk3sDg/initialising-cocoa-nsvaluetransformers" rel="alternate" type="text/html" />
   <updated>2009-03-26T02:09:00+00:00</updated>
   <id>http://geoffgarside.co.uk/2009/03/26/initialising-cocoa-nsvaluetransformers</id>
   <content type="html">&lt;p&gt;Just a quicky, I created my first custom Value Transformer this evening. Normally to register your transformer you have to do something like the following&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="objc"&gt;&lt;span class="lineno"&gt; 1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;initialize&lt;/span&gt;
&lt;span class="lineno"&gt; 2&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="lineno"&gt; 3&lt;/span&gt;     &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt; &lt;span class="n"&gt;initialiseValueTransformers&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="lineno"&gt; 4&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="lineno"&gt; 5&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;initialiseValueTransformers&lt;/span&gt;
&lt;span class="lineno"&gt; 6&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="lineno"&gt; 7&lt;/span&gt;     &lt;span class="n"&gt;LoginStatusTransformer&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;loginStatusTransformer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="lineno"&gt; 8&lt;/span&gt;         &lt;span class="p"&gt;[[[&lt;/span&gt;&lt;span class="n"&gt;LoginStatusTransformer&lt;/span&gt; &lt;span class="n"&gt;alloc&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;autorelease&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="lineno"&gt; 9&lt;/span&gt;     &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;LoginStatusTransformer&lt;/span&gt; &lt;span class="nl"&gt;setValueTransformer:&lt;/span&gt;&lt;span class="n"&gt;loginStatusTransformer&lt;/span&gt;
&lt;span class="lineno"&gt;10&lt;/span&gt;         &lt;span class="nl"&gt;forName:&lt;/span&gt;&lt;span class="s"&gt;@&amp;quot;LoginStatusTransformer&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="lineno"&gt;11&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;which hurt that part of my brain which likes clean code because of all the repetition.&lt;/p&gt;

&lt;p&gt;So I cooked up a nice little pre-processor macro to tidy it up&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="objc"&gt;&lt;span class="lineno"&gt;1&lt;/span&gt; &lt;span class="cp"&gt;#define init_transformer(klass) \&lt;/span&gt;
&lt;span class="lineno"&gt;2&lt;/span&gt; &lt;span class="cp"&gt;    klass *vt##klass = [[[klass alloc] init] autorelease]; \&lt;/span&gt;
&lt;span class="lineno"&gt;3&lt;/span&gt; &lt;span class="cp"&gt;    [klass setValueTransformer:vt##klass forName:@&amp;quot;&amp;quot;#klass]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;so now I have&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="objc"&gt;&lt;span class="lineno"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;initialiseValueTransformers&lt;/span&gt;
&lt;span class="lineno"&gt;2&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="lineno"&gt;3&lt;/span&gt;     &lt;span class="n"&gt;init_transformer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LoginStatusTransformer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="lineno"&gt;4&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;which will be expanded out to&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="objc"&gt;&lt;span class="lineno"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;initialiseValueTransformers&lt;/span&gt;
&lt;span class="lineno"&gt;2&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="lineno"&gt;3&lt;/span&gt;     &lt;span class="n"&gt;LoginStatusTransformer&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;vtLoginStatusTransformer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="lineno"&gt;4&lt;/span&gt;         &lt;span class="p"&gt;[[[&lt;/span&gt;&lt;span class="n"&gt;LoginStatusTransformer&lt;/span&gt; &lt;span class="n"&gt;alloc&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;autorelease&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="lineno"&gt;5&lt;/span&gt;     &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;LoginStatusTransformer&lt;/span&gt; &lt;span class="nl"&gt;setValueTransformer:&lt;/span&gt;&lt;span class="n"&gt;vtLoginStatusTransformer&lt;/span&gt; 
&lt;span class="lineno"&gt;6&lt;/span&gt;         &lt;span class="nl"&gt;forName:&lt;/span&gt;&lt;span class="s"&gt;@&amp;quot;LoginStatusTransformer&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="lineno"&gt;7&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;it seems to be working for me at the moment, any bugs in the macro please let me know.&lt;/p&gt;

&lt;h3&gt;Update&lt;/h3&gt;

&lt;p&gt;Ben Stiglitz pointed out that if you use the class name as the transformer name there is no need to register it and Keith Duncan mentioned that theres no need to call &lt;code&gt;[super initialize]&lt;/code&gt; so I've updated the sample to reflect this.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=rA3Twlk3sDg:9nltV7fwfjA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=rA3Twlk3sDg:9nltV7fwfjA:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?i=rA3Twlk3sDg:9nltV7fwfjA:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=rA3Twlk3sDg:9nltV7fwfjA:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/geoffgarside/~4/rA3Twlk3sDg" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://geoffgarside.co.uk/2009/03/26/initialising-cocoa-nsvaluetransformers</feedburner:origLink></entry>

 <entry>
   <title>Tweaking RDiscount</title>
   <link href="http://feedproxy.google.com/~r/geoffgarside/~3/R5Z-kS9SYFY/tweaking-rdiscount" rel="alternate" type="text/html" />
   <updated>2009-03-16T03:12:00+00:00</updated>
   <id>http://geoffgarside.co.uk/2009/03/16/tweaking-rdiscount</id>
   <content type="html">&lt;p&gt;As I mentioned in my previous post I'd had some issues with &lt;a href="http://pygments.org/"&gt;Pygments&lt;/a&gt; and &lt;a href="http://github.com/rtomayko/rdiscount/tree/master"&gt;RDiscount&lt;/a&gt;. I have been using &lt;a href="http://pygments.org/"&gt;Pygments&lt;/a&gt; to highlight my code blocks in my blog. Unfortunately right after using a code block with &lt;code&gt;linenos&lt;/code&gt; none of the markdown was being parsed anymore.&lt;/p&gt;

&lt;p&gt;The &lt;a href="http://www.pell.portland.or.us/~orc/Code/markdown/"&gt;Discount&lt;/a&gt; library upon which &lt;a href="http://github.com/rtomayko/rdiscount/tree/master"&gt;RDiscount&lt;/a&gt; is based has the ability to output a debug tree which shows the different blocks within the document. Things like paragraphs, quotes, code blocks and so on. Using this I was able to determine that the HTML block which contained the highlighted code was the last block being detected.&lt;/p&gt;

&lt;p&gt;The &lt;a href="http://pygments.org/"&gt;Pygments&lt;/a&gt; highlighted source with line numbers is actually rendered in a table. This table closes with&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="html"&gt;&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;and herein lay the problem. The &lt;a href="http://www.pell.portland.or.us/~orc/Code/markdown/"&gt;Discount&lt;/a&gt; library detects the closing HTML tag with the following function&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="c"&gt;&lt;span class="lineno"&gt; 1&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;Line&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="lineno"&gt; 2&lt;/span&gt; &lt;span class="nf"&gt;htmlblock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Paragraph&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="lineno"&gt; 3&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="lineno"&gt; 4&lt;/span&gt;     &lt;span class="n"&gt;Line&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="lineno"&gt; 5&lt;/span&gt;     &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;closesize&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="lineno"&gt; 6&lt;/span&gt;     &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;MAXTAG&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="lineno"&gt; 7&lt;/span&gt;  
&lt;span class="lineno"&gt; 8&lt;/span&gt;     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;selfclose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;MAXTAG&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="lineno"&gt; 9&lt;/span&gt;         &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="lineno"&gt;10&lt;/span&gt;         &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="lineno"&gt;11&lt;/span&gt;         &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="lineno"&gt;12&lt;/span&gt;     &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="lineno"&gt;13&lt;/span&gt;  
&lt;span class="lineno"&gt;14&lt;/span&gt;     &lt;span class="n"&gt;closesize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;&amp;lt;/%s&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="lineno"&gt;15&lt;/span&gt;  
&lt;span class="lineno"&gt;16&lt;/span&gt;     &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="lineno"&gt;17&lt;/span&gt;         &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;strncasecmp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;closesize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="lineno"&gt;18&lt;/span&gt;             &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="lineno"&gt;19&lt;/span&gt;             &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="lineno"&gt;20&lt;/span&gt;             &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="lineno"&gt;21&lt;/span&gt;         &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="lineno"&gt;22&lt;/span&gt;     &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="lineno"&gt;23&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="lineno"&gt;24&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;which as you might be able to tell, on line 17, checks the line for the presence of the HTML closing element. In the case of the &lt;a href="http://pygments.org/"&gt;Pygments&lt;/a&gt; closing element, this was not on its own line. While looking for &lt;code&gt;&amp;lt;/table&amp;gt;&lt;/code&gt; it would only read up to &lt;code&gt;&amp;lt;/td&amp;gt;&amp;lt;/t&lt;/code&gt; from the line before giving up.&lt;/p&gt;

&lt;p&gt;Testing with a pre-pygmentised file and pushing the &lt;code&gt;&amp;lt;/table&amp;gt;&lt;/code&gt; onto its own new line confirmed that this was the problem.&lt;/p&gt;

&lt;h2&gt;But how do we fix it?&lt;/h2&gt;

&lt;p&gt;Well I started out looking for C string searching functions, of course &lt;code&gt;strstr&lt;/code&gt; was the first candidate. Replacing line 17 of the aforementioned &lt;code&gt;htmlblock()&lt;/code&gt; function with&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="c"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;strstr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;seemed like a good idea, but running the &lt;a href="http://github.com/rtomayko/rdiscount/tree/master"&gt;RDiscount&lt;/a&gt; test suite revealed my naivety of the solution. With my change text such as &lt;code&gt;   &amp;lt;/table&amp;gt;&lt;/code&gt; was matched breaking HTML code examples, this wasn't good enough.&lt;/p&gt;

&lt;p&gt;I spent much longer than I really should have trying other solutions before having the critical &lt;strong&gt;Eureka&lt;/strong&gt; moment. I should add that prior to this moment I'd learnt of the more suitable &lt;code&gt;strcasestr()&lt;/code&gt; function to better match the &lt;code&gt;strncasecmp()&lt;/code&gt; function originally used.&lt;/p&gt;

&lt;p&gt;At any rate my &lt;strong&gt;Eureka&lt;/strong&gt; was realising that I was only ever going to need to search a string of closing tags, and that these closing tags would never be preceded by white space. Initially was thinking of using the CTYPE &lt;code&gt;isspace&lt;/code&gt; macro, but a far simpler solution also struck me.&lt;/p&gt;

&lt;p&gt;A closing tag, or string of closing tags will always start with a &lt;code&gt;&amp;lt;&lt;/code&gt;, so provided the line started with &lt;code&gt;&amp;lt;&lt;/code&gt; and then contained the respective closing tag I could reasonably safely assume the HTML block was being closed.&lt;/p&gt;

&lt;p&gt;So I next transformed line 17 of &lt;code&gt;htmlblock()&lt;/code&gt; to&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="c"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;&amp;#39;&amp;lt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;strcasestr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;and re-ran the &lt;a href="http://github.com/rtomayko/rdiscount/tree/master"&gt;RDiscount&lt;/a&gt; test suite to see if the tests passed, they did. Next I added a snippet of the &lt;a href="http://pygments.org/"&gt;Pygments&lt;/a&gt; table to one of the test files with some extra markdown after it, updated the expected output file as well and re-ran the test suite. Again it all passed perfectly.&lt;/p&gt;

&lt;p&gt;Once this was all done, I committed my changes to a &lt;a href="http://github.com/geoffgarside/rdiscount/tree/pygments-html"&gt;branch&lt;/a&gt; of the &lt;a href="http://github.com/geoffgarside/rdiscount/tree/master"&gt;fork&lt;/a&gt; I'd made of &lt;a href="http://github.com/rtomayko/rdiscount/tree/master"&gt;RDiscount&lt;/a&gt; and pushed them up to my &lt;a href="http://github.com/geoffgarside/rdiscount/tree/master"&gt;fork&lt;/a&gt; on &lt;a href="http://github.com/"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As I final test I updated the &lt;a href="http://www.pell.portland.or.us/~orc/Code/markdown/"&gt;Discount&lt;/a&gt; source as well and re-ran it over the file to output the debug tree again. I was pleased to see all the right blocks of the file being shown, lovely.&lt;/p&gt;

&lt;h2&gt;Update&lt;/h2&gt;

&lt;p&gt;My fork has been merged with the &lt;a href="http://github.com/rtomayko/rdiscount/commit/6bc35d19747f0ecc71223507663910ccf412b1af"&gt;master&lt;/a&gt; and been &lt;a href="http://github.com/rtomayko/rdiscount/commit/5d452caeff8373a1983e60d790a3dc406275ba18"&gt;refined&lt;/a&gt; as well.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=R5Z-kS9SYFY:zeFB5SpohRU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=R5Z-kS9SYFY:zeFB5SpohRU:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?i=R5Z-kS9SYFY:zeFB5SpohRU:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=R5Z-kS9SYFY:zeFB5SpohRU:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/geoffgarside/~4/R5Z-kS9SYFY" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://geoffgarside.co.uk/2009/03/16/tweaking-rdiscount</feedburner:origLink></entry>

 <entry>
   <title>Changing the blogging gear</title>
   <link href="http://feedproxy.google.com/~r/geoffgarside/~3/vWCJ9a9xHko/changing-the-blogging-gear" rel="alternate" type="text/html" />
   <updated>2009-03-16T02:44:00+00:00</updated>
   <id>http://geoffgarside.co.uk/2009/03/16/changing-the-blogging-gear</id>
   <content type="html">&lt;p&gt;I've recently been working on merging my two blogs together into one. One of them I host myself, the other is with &lt;a href="http://tumblr.com/"&gt;Tumblr&lt;/a&gt;. One has stagnated quite severely with the last update April 1st, 2008, the other only seems to get periodic and occasionally small updates.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://twitter.com/"&gt;Twitter&lt;/a&gt; has played a large part in the lack of updates to both of these sites. Through &lt;a href="http://twitter.com/"&gt;Twitter&lt;/a&gt; I can post short thoughts, URLs to items of potential interest and frequently have a more live dialogue with a group of people. I also don't plug either of my blogs to any degree really, I provide links to them, but I don't go telling people to read them.&lt;/p&gt;

&lt;p&gt;So what, you may ask, is the point in merging them at all? Well I still want to blog, but the point of blogging has changed. I now see blogging as a platform from which I can propose my thoughts or detail my current exploits when they merit it. My recent head injury was one such item mainly because I was asked for further details on it and it wouldn't fit the &lt;a href="http://twitter.com/"&gt;Twitter&lt;/a&gt; 140 character limit. The post on MySQL Replication was asked for by a friend of mine, while it was simplistic it helped me iron the process down in my head as well.&lt;/p&gt;

&lt;p&gt;So as the game is changing a bit I've been through all of my old blog posts, correcting spelling mistakes as well as changing some grammar here and there. Its a bit vain I know, but some of it read really poorly, I also went and wrapped nearly all of the code blogs so they'd be parsed by &lt;a href="http://pygments.org/"&gt;Pygments&lt;/a&gt;. I had some fun with that, especially with &lt;a href="http://github.com/rtomayko/rdiscount/tree/master"&gt;RDiscount&lt;/a&gt; which I am using to parse the Markdown post files. I managed to sort out those problems though and now I'm just down to sorting out some niggly little bits before I close down the other two and redirect them to one location.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=vWCJ9a9xHko:9Tpmqb7myPo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=vWCJ9a9xHko:9Tpmqb7myPo:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?i=vWCJ9a9xHko:9Tpmqb7myPo:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=vWCJ9a9xHko:9Tpmqb7myPo:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/geoffgarside/~4/vWCJ9a9xHko" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://geoffgarside.co.uk/2009/03/16/changing-the-blogging-gear</feedburner:origLink></entry>

 <entry>
   <title>Setting up MySQL Master Slave Replication</title>
   <link href="http://feedproxy.google.com/~r/geoffgarside/~3/xngG2nGPkIw/setting-up-mysql-master-slave-replication" rel="alternate" type="text/html" />
   <updated>2009-03-10T14:07:00+00:00</updated>
   <id>http://geoffgarside.co.uk/2009/03/10/setting-up-mysql-master-slave-replication</id>
   <content type="html">&lt;p&gt;Today I was asked to set up a MySQL Replication server to allow for &lt;em&gt;failover&lt;/em&gt; on one of the services we operate.&lt;/p&gt;

&lt;p&gt;A friend of mine also asked me to document the procedure as its been a while since he'd done it and couldn't remember. So here goes....&lt;/p&gt;

&lt;h2&gt;The Setup&lt;/h2&gt;

&lt;p&gt;I'll be doing all of this on &lt;a href="http://freebsd.org/" title="FreeBSD: The Power to Serve"&gt;FreeBSD 7.1&lt;/a&gt; servers and I'll be installing things from ports and then setting up the replication part.&lt;/p&gt;

&lt;p&gt;Installing MySQL is pretty much a breeze, I do tend to do this first though&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="sh"&gt;cat &lt;span class="s"&gt;&amp;lt;&amp;lt;EOF &amp;gt; /etc/make.conf&lt;/span&gt;
&lt;span class="s"&gt;.if ${.CURDIR:M*/databases/mysql5*}&lt;/span&gt;
&lt;span class="s"&gt;BUILD_OPTIMIZED=YES&lt;/span&gt;
&lt;span class="s"&gt;.endif&lt;/span&gt;
&lt;span class="s"&gt;EOF&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;to ensure that MySQL is built to run as quickly as possible. Then you have the simple commands to install the server, assuming you use &lt;code&gt;ports-mgmt/portupgrade&lt;/code&gt;&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="sh"&gt;portinstall databases/mysql50-server
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;once that has been done on each server then we can begin setting up the replication service.&lt;/p&gt;

&lt;h2&gt;Instruct the Master&lt;/h2&gt;

&lt;p&gt;First we need to tell the master that it is a master, we also need to make sure that it'll listen for slaves. So we need to add some things to the configuration file. You can use &lt;code&gt;/etc/my.cnf&lt;/code&gt; which is pretty global but I've opted for &lt;code&gt;/var/db/mysql/my.cnf&lt;/code&gt;&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ini"&gt;&lt;span class="lineno"&gt;1&lt;/span&gt; &lt;span class="k"&gt;[mysqld]&lt;/span&gt;
&lt;span class="lineno"&gt;2&lt;/span&gt; &lt;span class="na"&gt;bind-address&lt;/span&gt;      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;192.168.0.10&lt;/span&gt;
&lt;span class="lineno"&gt;3&lt;/span&gt; &lt;span class="na"&gt;server-id&lt;/span&gt;         &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;now, it will listen and it knows its the master.&lt;/p&gt;

&lt;p&gt;Next we need to instruct it where to keep the binary log file for replaying to the slaves so in the same file&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ini"&gt;&lt;span class="lineno"&gt;1&lt;/span&gt; &lt;span class="na"&gt;log-bin&lt;/span&gt;           &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;mysql-bin&lt;/span&gt;
&lt;span class="lineno"&gt;2&lt;/span&gt; &lt;span class="na"&gt;expire-logs-days&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;20&lt;/span&gt;
&lt;span class="lineno"&gt;3&lt;/span&gt; &lt;span class="na"&gt;max_binlog_size&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;104857600&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;so the binary log file will be written to &lt;code&gt;/var/db/mysql/mysql-bin&lt;/code&gt;, entries older than 20 days should be dropped and it shouldn't grow bigger than 100 megabytes.&lt;/p&gt;

&lt;p&gt;Finally we tell it exactly which databases we want to replicate, can you ignore this if you don't want to be specific. Again in the same file&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ini"&gt;&lt;span class="lineno"&gt;1&lt;/span&gt; &lt;span class="na"&gt;binlog-do-db&lt;/span&gt;      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;testdb&lt;/span&gt;
&lt;span class="lineno"&gt;2&lt;/span&gt; &lt;span class="na"&gt;binlog-ignore-db&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;mysql,test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;so only our &lt;code&gt;testdb&lt;/code&gt; table will be binary logged, additionally &lt;code&gt;mysql&lt;/code&gt; and &lt;code&gt;test&lt;/code&gt; databases will be ignored.&lt;/p&gt;

&lt;p&gt;Now you can restart your MySQL master server, to check that things are working you can connect to the server and run&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="sql"&gt;&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;SHOW&lt;/span&gt; &lt;span class="n"&gt;MASTER&lt;/span&gt; &lt;span class="n"&gt;STATUS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="c1"&gt;------------------+----------+---------------+-----------------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;File&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="k"&gt;Position&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Binlog_Do_DB&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Binlog_Ignore_DB&lt;/span&gt;      &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="c1"&gt;------------------+----------+---------------+-----------------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;bin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;000001&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;       &lt;span class="mi"&gt;98&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;testdb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;testdb&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; 
&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="c1"&gt;------------------+----------+---------------+-----------------------+&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;row&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;01&lt;/span&gt; &lt;span class="n"&gt;sec&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;and you should get something like above. You can also check to make sure the server is listening for connections with&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="sh"&gt;sockstat | grep mysql | grep tcp4
mysql    mysqld     90119 13 tcp4   192.168.0.10:3306   *:*
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;h2&gt;Creating a replication user&lt;/h2&gt;

&lt;p&gt;So we need to setup an account on the master server for the slave to use to authenticate itself. To do this we create a &lt;code&gt;REPLICATION SLAVE&lt;/code&gt; using the following MySQL statement&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="sql"&gt;&lt;span class="k"&gt;GRANT&lt;/span&gt; &lt;span class="n"&gt;REPLICATION&lt;/span&gt; &lt;span class="n"&gt;SLAVE&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;slave&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;slavehost&amp;#39;&lt;/span&gt; &lt;span class="n"&gt;IDENTIFIED&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;slavepass&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;we'll set these values on the slave as well so that it can authenticate to the master.&lt;/p&gt;

&lt;h2&gt;Instructing the Slave&lt;/h2&gt;

&lt;p&gt;Again I'll be keeping my configuration in &lt;code&gt;/var/db/mysql/my.cnf&lt;/code&gt;, so for the slave we need to tell it that it isn't top of the food chain and also who is. To do this we add&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ini"&gt;&lt;span class="lineno"&gt;1&lt;/span&gt; &lt;span class="k"&gt;[mysqld]&lt;/span&gt;
&lt;span class="lineno"&gt;2&lt;/span&gt; &lt;span class="na"&gt;bind-address&lt;/span&gt;          &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;192.168.0.11&lt;/span&gt;
&lt;span class="lineno"&gt;3&lt;/span&gt; &lt;span class="na"&gt;server-id&lt;/span&gt;             &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;to tell the Slave to listen for connections, this is so that external services which perhaps only need read access to the database can use the slave and save the master for writes.&lt;/p&gt;

&lt;p&gt;Next we must inform the Slave of its masters address and its authentication credentials for use when addressing the Master&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ini"&gt;&lt;span class="lineno"&gt;1&lt;/span&gt; &lt;span class="na"&gt;master-host&lt;/span&gt;           &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;192.168.0.10&lt;/span&gt;
&lt;span class="lineno"&gt;2&lt;/span&gt; &lt;span class="na"&gt;master-user&lt;/span&gt;           &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;slave&lt;/span&gt;
&lt;span class="lineno"&gt;3&lt;/span&gt; &lt;span class="na"&gt;master-password&lt;/span&gt;       &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;slavepass&lt;/span&gt;
&lt;span class="lineno"&gt;4&lt;/span&gt; &lt;span class="na"&gt;master-connect-retry&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;60&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Finally as we only want one database to be replicated, in my case at least, add the following line to the configuration file&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ini"&gt;&lt;span class="lineno"&gt;1&lt;/span&gt; &lt;span class="na"&gt;replicate-do-db&lt;/span&gt;       &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;testdb&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;so that only the &lt;code&gt;testdb&lt;/code&gt; database will be replicated.&lt;/p&gt;

&lt;h2&gt;Copying the database to the Slave&lt;/h2&gt;

&lt;p&gt;Firstly we need to know where in the binlog we are at the moment, so on the master server run the following command&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="sql"&gt;&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;SHOW&lt;/span&gt; &lt;span class="n"&gt;MASTER&lt;/span&gt; &lt;span class="n"&gt;STATUS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="c1"&gt;------------------+----------+---------------+-----------------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;File&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="k"&gt;Position&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Binlog_Do_DB&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Binlog_Ignore_DB&lt;/span&gt;      &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="c1"&gt;------------------+----------+---------------+-----------------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;bin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;000001&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="mi"&gt;327128&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;testdb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;testdb&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; 
&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="c1"&gt;------------------+----------+---------------+-----------------------+&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;remember the &lt;code&gt;File&lt;/code&gt; and &lt;code&gt;Position&lt;/code&gt; values as we'll need these to resynchronised the databases once the slave has a copy of the data.&lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;mysqldump&lt;/code&gt; create a copy of the master database to put onto the slave&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="sh"&gt;mysqldump --opt --databases testdb &amp;gt; /root/master-databases.sql
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Now copy the &lt;code&gt;/root/master-databases.sql&lt;/code&gt; file to the slave and then import it, assuming you copied it to &lt;code&gt;/root/master-databases.sql&lt;/code&gt; on the slave as well&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="sh"&gt;mysql &amp;lt; /root/master-databases.sql
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Now we need to synchronise the two copies. On the slave load up the &lt;code&gt;mysql&lt;/code&gt; client&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="sql"&gt;&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;STOP&lt;/span&gt; &lt;span class="n"&gt;SLAVE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;CHANGE&lt;/span&gt; &lt;span class="n"&gt;MASTER&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="n"&gt;MASTER_HOST&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;192.168.0.10&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;MASTER_USER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;slave_user&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MASTER_PASSWORD&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;slave_pass&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;MASTER_LOG_FILE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;mysql-bin.000001&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MASTER_LOG_POS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;327128&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;START&lt;/span&gt; &lt;span class="n"&gt;SLAVE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;and the changes will be synchronised between the two servers.&lt;/p&gt;

&lt;h2&gt;A quick test&lt;/h2&gt;

&lt;p&gt;Now its a good idea to make some test insertions into the master database and then check to see if they exist on the slave as well. I'll leave this part up to you...&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=xngG2nGPkIw:-eNBr_PHyMc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=xngG2nGPkIw:-eNBr_PHyMc:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?i=xngG2nGPkIw:-eNBr_PHyMc:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=xngG2nGPkIw:-eNBr_PHyMc:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/geoffgarside/~4/xngG2nGPkIw" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://geoffgarside.co.uk/2009/03/10/setting-up-mysql-master-slave-replication</feedburner:origLink></entry>

 <entry>
   <title>So what happened to me on Friday the 6th of March?</title>
   <link href="http://feedproxy.google.com/~r/geoffgarside/~3/35Gko_m_iNk/so-what-happened-to-me-on-friday-the-6th-of-march" rel="alternate" type="text/html" />
   <updated>2009-03-09T18:47:00+00:00</updated>
   <id>http://geoffgarside.co.uk/2009/03/09/so-what-happened-to-me-on-friday-the-6th-of-march</id>
   <content type="html">&lt;p&gt;As so many of these tales unravel it all started with alcohol. I'd been invited out by Claire for her brother Neils fiancé Alices birthday drinks do. This is only the second time I've met Alice, the first time at their engagement party. I've known Neil for a while as he used to work at the same company I'm at now.&lt;/p&gt;

&lt;p&gt;At any rate over the course of the night quite a few drinks where consumed.&lt;/p&gt;

&lt;p&gt;Towards the end of the evening, one or two people had started to go home, I felt a bit dizzy quite rapidly. Normally I get a slowly increasing buzz which I know well and use as a good indicator of when to stop drinking. I made my way to the toilets to get some water on my face, unfortunately there was a queue of people coming out of the toilets, so I decided to go back up the spiral staircase to get some air instead. The next couple of events are bit more patchy. I recall standing under the staircase, possibly letting some people past, something also makes me think I might have sat down under the stairs, maybe I was waiting to get into the toilets to splash my face. Things just sort of get a bit black and hazy from there.&lt;/p&gt;

&lt;p&gt;The next thing I remember is seeing Claire and the woman from the coat desk standing over me. Claire was pressing some blue paper towels to my forehead.
I don't specifically recall the first couple of questions but they were along the lines of "are you alright" and "how many fingers am I holding up". Then we came to the slightly more tricky questions of did I remember what happened. As you can probably guess at this point, I wasn't completely sure. I'd apparently been unconscious for a minute or so as well.&lt;/p&gt;

&lt;p&gt;After a few minutes the ambulance "drunk bus" arrived, and the paramedics had a look over me, took my blood pressure, checked my blood sugar and took my details. They said the wound seemed superficial but that someone should keep an eye on me and asked if I'd come with anyone else, I said no and that I'd met up with every body at the bar. Once they'd finished collecting my details the paramedic and I wandered back over to my friends and told them that I should be alright but that someone should keep an eye on me over night as it could be worse than it looked. If I started having blurred vision or started vomiting I should be taken to hospital to be checked out fully.&lt;/p&gt;

&lt;p&gt;Everyone came back out of the bar a few minutes later to decide what to do next, I think the party was winding down so most opted to return home. So we said farewell to each other amidst various Harry Potter comments. Claire offered to take me back to her house and keep an eye on me so we headed off in the direction of the tube. On the way back, before we caught the tube, she checked with one of her house mates that was away for the weekend to see if I could sleep in their bed for the night. Fortunately the tube is quite direct though the whole time I was wishing I had a hat to cover up my stupid forehead. When we got off the tube we had a rather pleasant walk to her house, it was good to chat without the noise of the bar.&lt;/p&gt;

&lt;p&gt;When we got to her house Claire stuck some bandages to my forehead and chin so that I wouldn't bleed all over her house mates pillow. We each then went to bed, as I couldn't quite sleep yet I posted a &lt;a href="http://twitpic.com/1w2lb"&gt;picture&lt;/a&gt; on twitter and then answered a few questions about it before finally putting head down to sleep.&lt;/p&gt;

&lt;p&gt;Around eight in the morning I woke up and checked my bandages, it was good having them there as my chin had bled a bit during the night. I left them in place and then lay back down in the bed for a bit to rest and run through the evening. After a little while I checked the internet to find some tips on speeding up the healing process. Vitamin C, Zinc and protein all seemed like best things to get, so I decided that I'd have a fry up with Orange Juice when I got home. The best hangover cure if ever there was one. A tasty multivitamin can follow that up for the Zinc. I also did some "Brain Training" as I figured it might help.&lt;/p&gt;

&lt;p&gt;Some time later I got up again and carefully remove the bandages from my face, I managed to loosen the scab on my chin from the bandage with water so I didn't tear it all off. At the same time I noticed some abrasions on the side of my face, quite shallow though and they'd scabbed up pretty quickly by the looks of things, a bit swollen though.&lt;/p&gt;

&lt;p&gt;Around 9.30 Claire came down to check on me, by this time I was feeling reasonably well, as she needed to pack up to go to a ball in the evening I decided I would make my way back home. She gave me some directions back to the tube station and I remembered most of it from the walk the opposite direction the night before.&lt;/p&gt;

&lt;p&gt;I got a couple of strange looks from people on the tube but mainly I kept my head down to avoid everyone. When I got back to Mile End I went into the new Tesco got my fry up supplies and some plasters. Then I had a nice big fry up when I got back to my flat.&lt;/p&gt;

&lt;p&gt;Later that day I discovered a couple other &lt;em&gt;party injuries&lt;/em&gt;, a decent sized but shallow cut on my shoulder and a skinned and bruised knee. None of it, bar the knee, is giving me any real pain and I've not had any dizziness or vomiting since the event.&lt;/p&gt;

&lt;h3&gt;So what &lt;em&gt;actually&lt;/em&gt; happened?&lt;/h3&gt;

&lt;p&gt;Well the best I can piece together is that my head collided with the spiral staircase by the toilets, though its difficult to work out exactly how I got the gash I did from that. The cut on my chin did swell up a little but, but as I've no pain in my jaw I don't think I hit it very hard at all. I've also no neck pains so I don't think I fell down the stairs at all. I suppose its possible that I just stood up into the edge of a stair, that would probably explain the vertical nature of the &lt;a href="http://files.geoffgarside.co.uk/headwound.jpg"&gt;gash&lt;/a&gt; though its not a straight wound.&lt;/p&gt;

&lt;h3&gt;But I wanna see a picture!!!&lt;/h3&gt;

&lt;p&gt;Ok fine, Jason took a pretty good one of it the other night.
&lt;img src="http://files.geoffgarside.co.uk/headwound.jpg" alt="headwound" /&gt;&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=35Gko_m_iNk:IMrrfcZvvUM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=35Gko_m_iNk:IMrrfcZvvUM:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?i=35Gko_m_iNk:IMrrfcZvvUM:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=35Gko_m_iNk:IMrrfcZvvUM:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/geoffgarside/~4/35Gko_m_iNk" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://geoffgarside.co.uk/2009/03/09/so-what-happened-to-me-on-friday-the-6th-of-march</feedburner:origLink></entry>

 <entry>
   <title>Proxying through complex situations</title>
   <link href="http://feedproxy.google.com/~r/geoffgarside/~3/Ggo52mbVFjQ/proxying-through-complex-situations" rel="alternate" type="text/html" />
   <updated>2009-02-06T16:54:00+00:00</updated>
   <id>http://geoffgarside.co.uk/2009/02/06/proxying-through-complex-situations</id>
   <content type="html">&lt;p&gt;I was recently in need of access to my Windows XP desktop machine which is has
been left at my parents house due to lack of space anywhere I've lived in
London. I had previously set up a port forwarding rule on their home router to
push any RDP connections through to my desktop. Annoyingly as I found these
didn't want to work. I don't know what is wrong with my parents router but it
won't forward any ports, this might have something to do with the DMZ which is
also turned on. I've never been a big fan of remote router access so I got on
to their file server via SSH, installed &lt;code&gt;elinks&lt;/code&gt; with SpiderMonkey javascript
support and attempted to connect to the router to see if I'd set up the port
forwarding. This didn't work as the javascript &lt;code&gt;location.replace&lt;/code&gt; is apparently
not a function. This left me a bit stumped as to how I might be able to pull
this off.&lt;/p&gt;

&lt;p&gt;After a bit of searching through the SSH manpage I gave the following a try&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ssh -D 8080 -f -C -q -N parents-fileserver
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;this created a SOCKS proxy through which I could tunnel into their local
network and view the routers management interface. It was after a bit of
unsuccessful playing here that I found out their router doesn't always forward
ports properly. This left me in a bit of conundrum.&lt;/p&gt;

&lt;h2&gt;Netcat&lt;/h2&gt;

&lt;p&gt;I would say that the majority of Unix people would have heard of Netcat, aka
&lt;code&gt;nc&lt;/code&gt;. Netcat is a networking tool which lets you do just about anything you
could possibly want to with TCP or UDP. So I wondered if I could create an
instance of &lt;code&gt;nc&lt;/code&gt; to listen on the RDP port and then somehow pass that through
to my desktop machine. A very quick google turned up this command&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="sh"&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;nc -l -p 3389 | nc 10.0.0.10 3389 | nc -b -l -p 3389
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;though many of the command switches had disappeared or their combinations were
now invalid I turned it into this&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="sh"&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;nc -l 3389 | nc 10.0.0.10 3389 | nc -l 3389
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;and tried to connect up to my desktop. This command should create an instance
of &lt;code&gt;nc&lt;/code&gt; that listens on the RDP port and pipes whatever it gets through to
another instance of &lt;code&gt;nc&lt;/code&gt; which is connected to my desktop machine, this again
pipes whatever it gets back through the listening port.&lt;/p&gt;

&lt;p&gt;This didn't work... at all.&lt;/p&gt;

&lt;p&gt;So a bit more googling turned up this on the freebsd mailing lists&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="sh"&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;mkfifo /tmp/fifo
&lt;span class="nv"&gt;$ &lt;/span&gt;nc -l 3389 &amp;lt; /tmp/fifo | nc 10.0.0.10 3389 &amp;gt; /tmp/fifo
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;this should again pipe anything hitting the server RDP port to the desktop RDP
port, the desktop RDP traffic gets written into &lt;code&gt;/tmp/fifo&lt;/code&gt; which is then sent
back to the originating client.&lt;/p&gt;

&lt;p&gt;This also didn't work... at all.&lt;/p&gt;

&lt;p&gt;So now I was at a bit of a loss, but the freebsd mailing list entry mentioned
a website from which they were basing their experiment on, so I went to check
that out. The bottom of the page mentioned an alternative solution using a
program called &lt;code&gt;socat&lt;/code&gt;. Ok, I thought, lets give that a try and installed that.&lt;/p&gt;

&lt;p&gt;So I ran the following command to create the &lt;code&gt;socat&lt;/code&gt; proxy&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="sh"&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;socat tcp4-listen:3389,reuseaddr,fork TCP:10.0.0.10:3389
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This worked... very, very well.&lt;/p&gt;

&lt;p&gt;So now when I need to get into my desktop machine I can SSH to the file server
and setup the proxy, do what I need to and then shut it down when I'm done.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=Ggo52mbVFjQ:bVLtbAb4yHw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=Ggo52mbVFjQ:bVLtbAb4yHw:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?i=Ggo52mbVFjQ:bVLtbAb4yHw:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=Ggo52mbVFjQ:bVLtbAb4yHw:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/geoffgarside/~4/Ggo52mbVFjQ" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://geoffgarside.co.uk/2009/02/06/proxying-through-complex-situations</feedburner:origLink></entry>

 <entry>
   <title>Ruby on Rails on Vimeo </title>
   <link href="http://feedproxy.google.com/~r/geoffgarside/~3/LDB1OE1Zv5M/ruby-on-rails-on-vimeo" rel="alternate" type="text/html" />
   <updated>2009-01-28T09:21:00+00:00</updated>
   <id>http://geoffgarside.co.uk/2009/01/28/ruby-on-rails-on-vimeo</id>
   <content type="html">&lt;p&gt;&lt;object type="application/x-shockwave-flash" width="400" height="300" data="http://vimeo.com/moogaloop.swf?clip_id=2979844&amp;amp;server=vimeo.com&amp;amp;fullscreen=1&amp;amp;show_title=1&amp;amp;show_byline=0&amp;amp;show_portrait=0&amp;amp;color=00ADEF"&gt;&lt;param name="quality" value="best" /&gt;&lt;param name="allowscriptaccess" value="always" /&gt;&lt;param name="allowfullscreen" value="true" /&gt;&lt;param name="scale" value="showAll" /&gt;&lt;param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=2979844&amp;amp;server=vimeo.com&amp;amp;fullscreen=1&amp;amp;show_title=1&amp;amp;show_byline=0&amp;amp;show_portrait=0&amp;amp;color=00ADEF" /&gt;&lt;embed src="http://www.vimeo.com/moogaloop.swf?clip_id=2979844&amp;amp;server=www.vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=0&amp;amp;show_portrait=0&amp;amp;color=00ADEF&amp;amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="300"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;

&lt;p&gt;Ruby on Rails on &lt;a href="http://vimeo.com/2979844"&gt;Vimeo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is brilliant to watch, it starts off in SVN and around 5:10 I think its been moved into git. At around 6:05 you might also spot a recognisable avatar ;-)&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=LDB1OE1Zv5M:t-IiZdSB36Q:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=LDB1OE1Zv5M:t-IiZdSB36Q:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?i=LDB1OE1Zv5M:t-IiZdSB36Q:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=LDB1OE1Zv5M:t-IiZdSB36Q:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/geoffgarside/~4/LDB1OE1Zv5M" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://geoffgarside.co.uk/2009/01/28/ruby-on-rails-on-vimeo</feedburner:origLink></entry>

 <entry>
   <title>My first Nu script</title>
   <link href="http://feedproxy.google.com/~r/geoffgarside/~3/VZCtI9Sos4U/my-first-nu-script" rel="alternate" type="text/html" />
   <updated>2009-01-17T00:49:00+00:00</updated>
   <id>http://geoffgarside.co.uk/2009/01/17/my-first-nu-script</id>
   <content type="html">&lt;p&gt;I get bored, quite easily and my desktop picture is no exception to this. Thankfully in Mac OS X, I believe Windows too, you can have a rotating desktop picture. By rotating, I don't mean spinning, rather I mean you provide a directory of images and the OS displays them in a random order. So every 5 minutes I get another image.&lt;/p&gt;

&lt;p&gt;Occasionally it will display and image which I am very bored of, or just don't like. In this case I then have to flip through the images in my &lt;em&gt;Desktop Pictures&lt;/em&gt; directory to find the offending image and remove it. Every time I had to do this I was sure there was an easier way. A couple months ago I found that the &lt;code&gt;~/Library/Preferences/com.apple.desktop.plist&lt;/code&gt; file contained the information which I required to get the image file name, and more portably the path used for the &lt;em&gt;Desktop Pictures&lt;/em&gt;. Originally I wrote up a small bash script to &lt;code&gt;grep&lt;/code&gt; the information I needed from the &lt;code&gt;defaults read&lt;/code&gt; output, but I never liked this. The reason I never liked this was that the &lt;code&gt;ChangePath&lt;/code&gt; and &lt;code&gt;LastName&lt;/code&gt; property list keys appeared something like three times in the file. So I was having to &lt;code&gt;tail&lt;/code&gt; the &lt;code&gt;grep&lt;/code&gt; output to only select the last one, as this is the one I cared about.&lt;/p&gt;

&lt;p&gt;What I really wanted was a way to use the &lt;code&gt;defaults&lt;/code&gt; program to access a slightly more complicated key structure than it would allow.&lt;/p&gt;

&lt;h3&gt;Along came Nu&lt;/h3&gt;

&lt;p&gt;&lt;a href="http://programming.nu/" title="Programming Nu"&gt;Nu&lt;/a&gt; is a &lt;a href="http://en.wikipedia.org/wiki/Lisp_programming_language" title="Lisp on Wikipedia"&gt;lisp&lt;/a&gt; like language written by &lt;a href="http://blog.neontology.com/" title="Tim Burks weblog"&gt;Tim Burks&lt;/a&gt; which allows access to the &lt;a href="http://en.wikipedia.org/wiki/Cocoa_API" title="Cocoa API on Wikipedia"&gt;Cocoa&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/Foundation_Kit" title="Foundation Kit on Wikipedia"&gt;Foundation&lt;/a&gt; API's in a scripting like shell (through &lt;code&gt;nush&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;The most I'd really used &lt;a href="http://programming.nu/" title="Programming Nu"&gt;Nu&lt;/a&gt; for at this point was just playing around with the &lt;a href="http://en.wikipedia.org/wiki/Cocoa_API" title="Cocoa API on Wikipedia"&gt;Cocoa&lt;/a&gt; API's, messing with functions and seeing how things worked. This is one of the most frequent uses I have of &lt;a href="http://programming.nu/" title="Programming Nu"&gt;Nu&lt;/a&gt; because it lets me essentially debug interactively in a sensible way.&lt;/p&gt;

&lt;p&gt;Given my rather amateur usage of &lt;a href="http://programming.nu/" title="Programming Nu"&gt;Nu&lt;/a&gt; so far I wanted to try and use it in its own right. Given my issues with the &lt;code&gt;defaults&lt;/code&gt; program for accessing complex key paths, and knowing an &lt;code&gt;NSDictionary&lt;/code&gt; would do this easily I thought this would be a good little dip in the sparkling &lt;a href="http://programming.nu/" title="Programming Nu"&gt;Nu&lt;/a&gt; waters.&lt;/p&gt;

&lt;p&gt;The script below is what I came up with, it is pretty simple, and pretty self explanatory if you already know the &lt;a href="http://en.wikipedia.org/wiki/Cocoa_API" title="Cocoa API on Wikipedia"&gt;Cocoa&lt;/a&gt; API's. As a simple walkthrough though&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Check to see if the script was called with the "-rm" argument

&lt;ol&gt;
&lt;li&gt;Set &lt;code&gt;shouldOfferToRemove&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt; if it did, &lt;code&gt;nil&lt;/code&gt; if not&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Read in the &lt;code&gt;com.apple.desktop.plist&lt;/code&gt; file contents&lt;/li&gt;
&lt;li&gt;Get the dictionary for the &lt;em&gt;Background/default&lt;/em&gt; key&lt;/li&gt;
&lt;li&gt;Extract the &lt;em&gt;ChangePath&lt;/em&gt; value which is the path to the &lt;em&gt;Desktop Pictures&lt;/em&gt;
directory.&lt;/li&gt;
&lt;li&gt;Extract the &lt;em&gt;LastName&lt;/em&gt; value which is the file name of the image file&lt;/li&gt;
&lt;li&gt;Print the name of the image file&lt;/li&gt;
&lt;li&gt;Prompt the user to delete the file if requested

&lt;ol&gt;
&lt;li&gt;Delete the file if instructed&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;The most complicated portion of the script is the part where the response to
either delete or leave the file is read.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="cl"&gt;&lt;span class="lineno"&gt;1&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nv"&gt;input&lt;/span&gt; &lt;span class="p"&gt;(((&lt;/span&gt;&lt;span class="nv"&gt;NSString&lt;/span&gt; &lt;span class="nv"&gt;alloc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="lineno"&gt;2&lt;/span&gt;     &lt;span class="nv"&gt;initWithData:&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nv"&gt;NSFileHandle&lt;/span&gt; &lt;span class="nv"&gt;fileHandleWithStandardInput&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;availableData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="lineno"&gt;3&lt;/span&gt;     &lt;span class="nv"&gt;encoding:NSUTF8StringEncoding&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="lineno"&gt;4&lt;/span&gt;         &lt;span class="nv"&gt;stringByTrimmingCharactersInSet:&lt;/span&gt;
&lt;span class="lineno"&gt;5&lt;/span&gt;             &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;NSCharacterSet&lt;/span&gt; &lt;span class="nv"&gt;whitespaceAndNewlineCharacterSet&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;this section could be broken down a bit to something more like the following&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="cl"&gt;&lt;span class="lineno"&gt;1&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nv"&gt;stdin&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;NSFileHandle&lt;/span&gt; &lt;span class="nv"&gt;fileHandleWithStandardInput&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="lineno"&gt;2&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nv"&gt;inputData&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;stdin&lt;/span&gt; &lt;span class="nv"&gt;availableData&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="lineno"&gt;3&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nv"&gt;inputString&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nv"&gt;NSString&lt;/span&gt; &lt;span class="nv"&gt;alloc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;initWithData:inputData&lt;/span&gt;
&lt;span class="lineno"&gt;4&lt;/span&gt;   &lt;span class="nv"&gt;encoding:NSUTF8StringEncoding&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="lineno"&gt;5&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nv"&gt;trimSet&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;NSCharacterSet&lt;/span&gt; &lt;span class="nv"&gt;whitespaceAndNewlineCharacterSet&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="lineno"&gt;6&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nv"&gt;input&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;inputString&lt;/span&gt; &lt;span class="nv"&gt;stringByTrimmingCharactersInSet:trimSet&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;which does give a better indication of the operations being carried out, firstly
a file handle to the input stream is obtained, then the &lt;code&gt;availableData&lt;/code&gt; is read.
The &lt;code&gt;availableData&lt;/code&gt; returns whatever the user types before hitting &lt;em&gt;Enter&lt;/em&gt;.
The next couple of lines convert the &lt;code&gt;NSData&lt;/code&gt; into an &lt;code&gt;NSString&lt;/code&gt; and then trim
any whitespace or newline characters in the string. This lets the script more
easily compare the input against "y" and "Y".&lt;/p&gt;

&lt;p&gt;So without further ado, here is the script (also on &lt;a href="http://gist.github.com/48202" title="Gist: 48202 - Mac OS X Current Background script"&gt;gist&lt;/a&gt;)&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="cl"&gt;&lt;span class="lineno"&gt; 1&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nv"&gt;!/usr/bin/env&lt;/span&gt; &lt;span class="nv"&gt;nush&lt;/span&gt;
&lt;span class="lineno"&gt; 2&lt;/span&gt; &lt;span class="c1"&gt;; Useful script for when you have a rotating background on Mac OS X&lt;/span&gt;
&lt;span class="lineno"&gt; 3&lt;/span&gt; &lt;span class="c1"&gt;; this script will tell you which image is currently being displayed.&lt;/span&gt;
&lt;span class="lineno"&gt; 4&lt;/span&gt; &lt;span class="c1"&gt;; If you add -rm when calling the command then it will provide you with&lt;/span&gt;
&lt;span class="lineno"&gt; 5&lt;/span&gt; &lt;span class="c1"&gt;; prompt to let you delete the background.&lt;/span&gt;
&lt;span class="lineno"&gt; 6&lt;/span&gt; &lt;span class="c1"&gt;;&lt;/span&gt;
&lt;span class="lineno"&gt; 7&lt;/span&gt; &lt;span class="c1"&gt;; Installation:&lt;/span&gt;
&lt;span class="lineno"&gt; 8&lt;/span&gt; &lt;span class="c1"&gt;;  Copy this into something like ~/bin/current_background and then&lt;/span&gt;
&lt;span class="lineno"&gt; 9&lt;/span&gt; &lt;span class="c1"&gt;;  $ chmod 750 ~/bin/current_background&lt;/span&gt;
&lt;span class="lineno"&gt;10&lt;/span&gt; &lt;span class="c1"&gt;;  then use :D&lt;/span&gt;
&lt;span class="lineno"&gt;11&lt;/span&gt; &lt;span class="c1"&gt;;&lt;/span&gt;
&lt;span class="lineno"&gt;12&lt;/span&gt; &lt;span class="c1"&gt;; Usage: (assuming you call it current_background)&lt;/span&gt;
&lt;span class="lineno"&gt;13&lt;/span&gt; &lt;span class="c1"&gt;; Show the current background image filename&lt;/span&gt;
&lt;span class="lineno"&gt;14&lt;/span&gt; &lt;span class="c1"&gt;;  $ current_background&lt;/span&gt;
&lt;span class="lineno"&gt;15&lt;/span&gt; &lt;span class="c1"&gt;;  Current desktop image is background-1.jpg&lt;/span&gt;
&lt;span class="lineno"&gt;16&lt;/span&gt; &lt;span class="c1"&gt;; Show and optionally delete the current background image file&lt;/span&gt;
&lt;span class="lineno"&gt;17&lt;/span&gt; &lt;span class="c1"&gt;;  $ current_background -rm&lt;/span&gt;
&lt;span class="lineno"&gt;18&lt;/span&gt; &lt;span class="c1"&gt;;  Current desktop image is background-1.jpg&lt;/span&gt;
&lt;span class="lineno"&gt;19&lt;/span&gt; &lt;span class="c1"&gt;;  Are you sure you want to delete background-1.jpg [y/N]: &lt;/span&gt;
&lt;span class="lineno"&gt;20&lt;/span&gt; &lt;span class="c1"&gt;;  y&lt;/span&gt;
&lt;span class="lineno"&gt;21&lt;/span&gt; &lt;span class="c1"&gt;;  Background background-1.jpg has been deleted&lt;/span&gt;
&lt;span class="lineno"&gt;22&lt;/span&gt; &lt;span class="c1"&gt;;&lt;/span&gt;
&lt;span class="lineno"&gt;23&lt;/span&gt; &lt;span class="c1"&gt;; Bugs:&lt;/span&gt;
&lt;span class="lineno"&gt;24&lt;/span&gt; &lt;span class="c1"&gt;;  1. When prompting for user input I can&amp;#39;t seem to flush stdout manually&lt;/span&gt;
&lt;span class="lineno"&gt;25&lt;/span&gt; &lt;span class="c1"&gt;;     so I have to print a new line character in order to show the prompt.&lt;/span&gt;
&lt;span class="lineno"&gt;26&lt;/span&gt; &lt;span class="c1"&gt;;&lt;/span&gt;
&lt;span class="lineno"&gt;27&lt;/span&gt; 
&lt;span class="lineno"&gt;28&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nv"&gt;processInfo&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;NSProcessInfo&lt;/span&gt; &lt;span class="nv"&gt;processInfo&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="lineno"&gt;29&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nv"&gt;args&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;processInfo&lt;/span&gt; &lt;span class="nv"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="lineno"&gt;30&lt;/span&gt; 
&lt;span class="lineno"&gt;31&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;eq&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;args&lt;/span&gt; &lt;span class="nb"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;eq&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;args&lt;/span&gt; &lt;span class="nv"&gt;objectAtIndex:2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;-rm&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="lineno"&gt;32&lt;/span&gt;     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nv"&gt;shouldOfferToRemove&lt;/span&gt; &lt;span class="no"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="lineno"&gt;33&lt;/span&gt;     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;else&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nv"&gt;shouldOfferToRemove&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="lineno"&gt;34&lt;/span&gt; 
&lt;span class="lineno"&gt;35&lt;/span&gt; &lt;span class="c1"&gt;;; Get the dictionary&lt;/span&gt;
&lt;span class="lineno"&gt;36&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nv"&gt;plist&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;~/Library/Preferences/com.apple.desktop.plist&amp;quot;&lt;/span&gt; &lt;span class="nv"&gt;stringByExpandingTildeInPath&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="lineno"&gt;37&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nv"&gt;prefs&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;NSDictionary&lt;/span&gt; &lt;span class="nv"&gt;dictionaryWithContentsOfFile:plist&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="lineno"&gt;38&lt;/span&gt; 
&lt;span class="lineno"&gt;39&lt;/span&gt; &lt;span class="c1"&gt;;; Drill down to the dictionary key we care about&lt;/span&gt;
&lt;span class="lineno"&gt;40&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nv"&gt;default&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nv"&gt;prefs&lt;/span&gt; &lt;span class="nv"&gt;valueForKey:&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Background&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;valueForKey:&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;default&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="lineno"&gt;41&lt;/span&gt; 
&lt;span class="lineno"&gt;42&lt;/span&gt; &lt;span class="c1"&gt;;; Extract the fields we need&lt;/span&gt;
&lt;span class="lineno"&gt;43&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nv"&gt;changePath&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;default&lt;/span&gt; &lt;span class="nv"&gt;valueForKey:&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ChangePath&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="lineno"&gt;44&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nv"&gt;currentImage&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;default&lt;/span&gt; &lt;span class="nv"&gt;valueForKey:&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;LastName&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="lineno"&gt;45&lt;/span&gt; 
&lt;span class="lineno"&gt;46&lt;/span&gt; &lt;span class="c1"&gt;;; Print the information&lt;/span&gt;
&lt;span class="lineno"&gt;47&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;puts&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Current desktop image is #{currentImage}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="lineno"&gt;48&lt;/span&gt; 
&lt;span class="lineno"&gt;49&lt;/span&gt; &lt;span class="c1"&gt;;; Offer to delete&lt;/span&gt;
&lt;span class="lineno"&gt;50&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;eq&lt;/span&gt; &lt;span class="no"&gt;t&lt;/span&gt; &lt;span class="nv"&gt;shouldOfferToRemove&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="lineno"&gt;51&lt;/span&gt;     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Are you sure you want to delete #{currentImage} [y/N]: \n&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="lineno"&gt;52&lt;/span&gt;     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nv"&gt;input&lt;/span&gt; &lt;span class="p"&gt;(((&lt;/span&gt;&lt;span class="nv"&gt;NSString&lt;/span&gt; &lt;span class="nv"&gt;alloc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="lineno"&gt;53&lt;/span&gt;         &lt;span class="nv"&gt;initWithData:&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nv"&gt;NSFileHandle&lt;/span&gt; &lt;span class="nv"&gt;fileHandleWithStandardInput&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;availableData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="lineno"&gt;54&lt;/span&gt;         &lt;span class="nv"&gt;encoding:NSUTF8StringEncoding&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="lineno"&gt;55&lt;/span&gt;             &lt;span class="nv"&gt;stringByTrimmingCharactersInSet:&lt;/span&gt;
&lt;span class="lineno"&gt;56&lt;/span&gt;                 &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;NSCharacterSet&lt;/span&gt; &lt;span class="nv"&gt;whitespaceAndNewlineCharacterSet&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="lineno"&gt;57&lt;/span&gt;     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;or&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;input&lt;/span&gt; &lt;span class="nv"&gt;isEqualToString:&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;y&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;input&lt;/span&gt; &lt;span class="nv"&gt;isEqualToString:&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Y&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="lineno"&gt;58&lt;/span&gt;         &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nv"&gt;fm&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;NSFileManager&lt;/span&gt; &lt;span class="nv"&gt;defaultManager&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="lineno"&gt;59&lt;/span&gt;         &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nv"&gt;path&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;changePath&lt;/span&gt; &lt;span class="nv"&gt;stringByAppendingPathComponent:currentImage&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="lineno"&gt;60&lt;/span&gt;         &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;fm&lt;/span&gt; &lt;span class="nv"&gt;removeFileAtPath:path&lt;/span&gt; &lt;span class="nv"&gt;handler:nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="lineno"&gt;61&lt;/span&gt;             &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;puts&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Background #{currentImage} has been deleted&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="lineno"&gt;62&lt;/span&gt;             &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;else&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;puts&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Background #{currentImage} could not be deleted&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="lineno"&gt;63&lt;/span&gt;         &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;else&lt;/span&gt;
&lt;span class="lineno"&gt;64&lt;/span&gt;             &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;puts&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Background #{currentImage} has not been deleted&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;



&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=VZCtI9Sos4U:Y6QbNUdu4ZA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=VZCtI9Sos4U:Y6QbNUdu4ZA:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?i=VZCtI9Sos4U:Y6QbNUdu4ZA:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=VZCtI9Sos4U:Y6QbNUdu4ZA:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/geoffgarside/~4/VZCtI9Sos4U" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://geoffgarside.co.uk/2009/01/17/my-first-nu-script</feedburner:origLink></entry>

 <entry>
   <title>What the Fedora developers failed to realize</title>
   <link href="http://feedproxy.google.com/~r/geoffgarside/~3/jVEDU-qfvgg/what-the-fedora-developers-failed-to-realize" rel="alternate" type="text/html" />
   <updated>2009-01-13T10:26:00+00:00</updated>
   <id>http://geoffgarside.co.uk/2009/01/13/what-the-fedora-developers-failed-to-realize</id>
   <content type="html">&lt;blockquote&gt;&lt;p&gt;What the Fedora developers failed to realize, however, is that the USS Leonidas was a derelict vessel that the Union army obtained to intentionally sink&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="http://arstechnica.com/journals/linux.ars/2009/01/12/fedora-11-codenamed-leonidas-will-kick-bad-guys-into-pit" title="Regarding the Fedora 11 codename"&gt;Source: Regarding the Fedora 11 codename&lt;/a&gt;&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=jVEDU-qfvgg:W0oLpKQCF3c:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=jVEDU-qfvgg:W0oLpKQCF3c:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?i=jVEDU-qfvgg:W0oLpKQCF3c:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=jVEDU-qfvgg:W0oLpKQCF3c:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/geoffgarside/~4/jVEDU-qfvgg" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://geoffgarside.co.uk/2009/01/13/what-the-fedora-developers-failed-to-realize</feedburner:origLink></entry>

 <entry>
   <title>Apple Wish: Xcode Building Embedded Projects</title>
   <link href="http://feedproxy.google.com/~r/geoffgarside/~3/EpGVj8EBYzo/apple-wish-xcode-building-embedded-projects" rel="alternate" type="text/html" />
   <updated>2009-01-04T01:43:00+00:00</updated>
   <id>http://geoffgarside.co.uk/2009/01/04/apple-wish-xcode-building-embedded-projects</id>
   <content type="html">&lt;p&gt;I've been spending quite a lot of my time recently using &lt;a href="http://www.apple.com/"&gt;Apple&lt;/a&gt;'s &lt;a href="http://www.apple.com/xcode/"&gt;Xcode&lt;/a&gt; just hacking on things which scratch a bit of an itch I get from time to time. Mainly I've been working on developing Mac OS frameworks for a couple purposes and I recently wanted to make a GUI demo app which used my framework, so I created a new project and use a &lt;a href="http://git-scm.com/"&gt;git&lt;/a&gt; &lt;code&gt;submodule&lt;/code&gt; to import the framework project. This all worked just fine, I was able to hook in the framework project to the demo project, set up the framework as a dependency of the GUI app and slapped the old &lt;em&gt;Build&lt;/em&gt; button and got two errors.&lt;/p&gt;

&lt;p&gt;Seems Xcode first builds the framework into &lt;code&gt;Framework/build/Debug/Framework.framework&lt;/code&gt; and then the GUI app into &lt;code&gt;build/Debug/Gui.app&lt;/code&gt; which means the GUI app can't find the framework to get the headers from.&lt;/p&gt;

&lt;h2&gt;What are our options?&lt;/h2&gt;

&lt;p&gt;Well what is required is for the build directories of both projects to be the same. You've got a couple of choices here. You can set an &lt;a href="http://www.apple.com/xcode/"&gt;Xcode&lt;/a&gt; wide preference and build all projects into a specific directory, or you can set the build directory in each of the projects (or just one) to make them the same. Lets explore the latter for the sake of argument as its the least disruptive to other projects.&lt;/p&gt;

&lt;h3&gt;Option 1&lt;/h3&gt;

&lt;p&gt;The first option, which is advocated in &lt;a href="http://www.amazon.co.uk/Xcode-3-Unleashed-Fritz-Anderson/dp/0321552636"&gt;Xcode 3 Unleashed&lt;/a&gt;, is to place the two projects in the same directory. In this case you have two &lt;code&gt;.xcodeproj&lt;/code&gt; files in your project directory, which therefore use the same &lt;code&gt;build&lt;/code&gt; directory. The downside to this method is that it doesn't work terribly well with &lt;a href="http://git-scm.com/"&gt;git&lt;/a&gt; submodules as each submodule has to exist as a separate folder.&lt;/p&gt;

&lt;p&gt;So because of the requirement to use &lt;a href="http://git-scm.com/"&gt;git&lt;/a&gt; submodules this method isn't really that feasible.&lt;/p&gt;

&lt;h3&gt;Option 2&lt;/h3&gt;

&lt;p&gt;A second option might be to change the sub project to build into &lt;code&gt;../build&lt;/code&gt; which is the build directory of the &lt;em&gt;primary&lt;/em&gt; project. This has the benefit of keeping the build results in the logical place of the &lt;em&gt;primary&lt;/em&gt; project. The down side is that you have to modify the submodule in order to make it work. While in most cases if you &lt;code&gt;git pull&lt;/code&gt; on the submodule to update the source it shouldn't break it but it is a nuisance none the less. So for this reason I also don't really like this option either.&lt;/p&gt;

&lt;h3&gt;Option 3&lt;/h3&gt;

&lt;p&gt;The final option would be to change our GUI project to use the build directory to use the build directory of the framework project. This keeps us from having to modify the submodule but I personally don't like this solution as it means our &lt;em&gt;primary&lt;/em&gt; project in this case is building into the space of a &lt;em&gt;sub&lt;/em&gt; project.&lt;/p&gt;

&lt;h2&gt;What would be better?&lt;/h2&gt;

&lt;p&gt;So why is this a wishlist item? Well I'd personally like to be able to override the &lt;em&gt;sub&lt;/em&gt; project build directory in the &lt;em&gt;primary&lt;/em&gt; project. So you'd be able to &lt;em&gt;Get Info&lt;/em&gt; on the &lt;code&gt;Framework.xcodeproj&lt;/code&gt; in your &lt;em&gt;Groups &amp;amp; Files&lt;/em&gt; pane and change the build directory. This would then either build the &lt;em&gt;sub&lt;/em&gt; project and then copy those contents into the &lt;em&gt;primary&lt;/em&gt; projects build directory, or else just have the project when its being built by the &lt;em&gt;primary&lt;/em&gt; build into the &lt;em&gt;primary&lt;/em&gt; &lt;code&gt;build&lt;/code&gt; directory.&lt;/p&gt;

&lt;h2&gt;Update: A Stop Gap&lt;/h2&gt;

&lt;p&gt;Played around a bit further and I &lt;em&gt;believe&lt;/em&gt; the &lt;em&gt;Frameworks Search Paths&lt;/em&gt; build configuration setting is possibly an appropriate solution. You can set this to say &lt;code&gt;Framework/build/Debug&lt;/code&gt; for your Debug configuration and then the compiler can find your framework project correctly for compiling. All the changes are happily in your &lt;em&gt;primary&lt;/em&gt; project and it makes sense that it should have to search into the Framework directory for the right files. I'm a bit happier now :-)&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=EpGVj8EBYzo:hmNlgN22ipg:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=EpGVj8EBYzo:hmNlgN22ipg:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?i=EpGVj8EBYzo:hmNlgN22ipg:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=EpGVj8EBYzo:hmNlgN22ipg:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/geoffgarside/~4/EpGVj8EBYzo" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://geoffgarside.co.uk/2009/01/04/apple-wish-xcode-building-embedded-projects</feedburner:origLink></entry>

 <entry>
   <title>A boy with pointy ears</title>
   <link href="http://feedproxy.google.com/~r/geoffgarside/~3/5xunMkSLVCc/a-boy-with-pointy-ears" rel="alternate" type="text/html" />
   <updated>2008-12-16T17:13:00+00:00</updated>
   <id>http://geoffgarside.co.uk/2008/12/16/a-boy-with-pointy-ears</id>
   <content type="html">&lt;blockquote&gt;&lt;p&gt;Next we see a much shorter growing up story – one of a boy with pointy ears. He starts off small and cute with pointy ears. Then gets bigger (but still with the ears), and turns into someone that modern viewers might recognise as Sylar from Heroes.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="http://www.guardian.co.uk/film/2008/dec/16/star-trek-trailer-review"&gt;Star Trek trailer: all 12-year-olds and whizz-bang action&lt;/a&gt;&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=5xunMkSLVCc:5ptQB92rdwo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=5xunMkSLVCc:5ptQB92rdwo:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?i=5xunMkSLVCc:5ptQB92rdwo:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=5xunMkSLVCc:5ptQB92rdwo:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/geoffgarside/~4/5xunMkSLVCc" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://geoffgarside.co.uk/2008/12/16/a-boy-with-pointy-ears</feedburner:origLink></entry>

 <entry>
   <title>But better to be addicted to smartphones...</title>
   <link href="http://feedproxy.google.com/~r/geoffgarside/~3/zbJzwqUGb7M/but-better-to-be-addicted-to-smartphones" rel="alternate" type="text/html" />
   <updated>2008-12-10T18:07:00+00:00</updated>
   <id>http://geoffgarside.co.uk/2008/12/10/but-better-to-be-addicted-to-smartphones</id>
   <content type="html">&lt;blockquote&gt;&lt;p&gt;But better to be addicted to smartphones and gismos than cocaine or sex, I suppose. Well, I don’t know, the result is the same after all, very little sleep, great expense and horrific mess everywhere.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="http://www.stephenfry.com/blog/2008/12/11/gee-one-bold-storm-coming-up%E2%80%A6/"&gt;The New Adventures of Mr Stephen Fry&lt;/a&gt;&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=zbJzwqUGb7M:NhAkdTnkQDk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=zbJzwqUGb7M:NhAkdTnkQDk:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?i=zbJzwqUGb7M:NhAkdTnkQDk:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=zbJzwqUGb7M:NhAkdTnkQDk:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/geoffgarside/~4/zbJzwqUGb7M" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://geoffgarside.co.uk/2008/12/10/but-better-to-be-addicted-to-smartphones</feedburner:origLink></entry>

 <entry>
   <title>My iPod is inspired</title>
   <link href="http://feedproxy.google.com/~r/geoffgarside/~3/weZrlRWm7o0/my-ipod-is-inspired" rel="alternate" type="text/html" />
   <updated>2008-11-13T13:58:00+00:00</updated>
   <id>http://geoffgarside.co.uk/2008/11/13/my-ipod-is-inspired</id>
   <content type="html">&lt;p&gt;The other morning my iPod played the following songs:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Follow the Cops Back Home by Placebo&lt;/li&gt;
&lt;li&gt;Evergreen by Faithless&lt;/li&gt;
&lt;li&gt;Starting Over by The Crystal Method&lt;/li&gt;
&lt;li&gt;Angels by Within Temptation&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;I'm still not quite sure why these songs flow so well into each other but the sequence really is superb.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=weZrlRWm7o0:gE2h7DUkbso:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=weZrlRWm7o0:gE2h7DUkbso:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?i=weZrlRWm7o0:gE2h7DUkbso:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=weZrlRWm7o0:gE2h7DUkbso:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/geoffgarside/~4/weZrlRWm7o0" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://geoffgarside.co.uk/2008/11/13/my-ipod-is-inspired</feedburner:origLink></entry>

 <entry>
   <title>Jeff Dunham - Achmed the Dead Terrorist </title>
   <link href="http://feedproxy.google.com/~r/geoffgarside/~3/D3u2teFHiLk/jeff-dunham-achmed-the-dead-terrorist" rel="alternate" type="text/html" />
   <updated>2008-10-31T18:27:00+00:00</updated>
   <id>http://geoffgarside.co.uk/2008/10/31/jeff-dunham-achmed-the-dead-terrorist</id>
   <content type="html">&lt;p&gt;&lt;object width="400" height="336"&gt;&lt;param name="movie" value="http://www.youtube.com/v/1uwOL4rB-go&amp;amp;rel=0&amp;amp;egm=0&amp;amp;showinfo=0&amp;amp;fs=1"&gt;&lt;/param&gt;&lt;param name="wmode" value="transparent"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/1uwOL4rB-go&amp;amp;rel=0&amp;amp;egm=0&amp;amp;showinfo=0&amp;amp;fs=1" type="application/x-shockwave-flash" width="400" height="336" allowFullScreen="true" wmode="transparent"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://uk.youtube.com/watch?v=1uwOL4rB-go&amp;amp;feature=related"&gt;Jeff Dunham - Achmed the Dead Terrorist&lt;/a&gt; (via &lt;a href="http://youtube.com/user/KrowBatellio"&gt;KrowBatellio&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Not very &lt;em&gt;PC&lt;/em&gt; but still quite hilarious.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=D3u2teFHiLk:kWfRh7aX0g8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=D3u2teFHiLk:kWfRh7aX0g8:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?i=D3u2teFHiLk:kWfRh7aX0g8:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/geoffgarside?a=D3u2teFHiLk:kWfRh7aX0g8:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/geoffgarside?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/geoffgarside/~4/D3u2teFHiLk" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://geoffgarside.co.uk/2008/10/31/jeff-dunham-achmed-the-dead-terrorist</feedburner:origLink></entry>

 
</feed>

