<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>char1es.net &#187; Code Hacking</title>
	<atom:link href="http://char1es.net/category/code-hacking/feed/" rel="self" type="application/rss+xml" />
	<link>http://char1es.net</link>
	<description>musings of a peripatetic</description>
	<lastBuildDate>Wed, 11 Aug 2010 06:41:38 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>twitterd in Python</title>
		<link>http://char1es.net/2009/07/08/twitterd-in-python/</link>
		<comments>http://char1es.net/2009/07/08/twitterd-in-python/#comments</comments>
		<pubDate>Thu, 09 Jul 2009 04:24:57 +0000</pubDate>
		<dc:creator>Nathan</dc:creator>
				<category><![CDATA[Code Hacking]]></category>
		<category><![CDATA[Geek out]]></category>
		<category><![CDATA[twitter finger]]></category>

		<guid isPermaLink="false">http://char1es.net/?p=273</guid>
		<description><![CDATA[So a while ago I decided that twitter is the new finger albeit more palitable for the masses and wrote twitterd in perl. I&#8217;ve been using this to update my twitter and facebook status ever since. A couple of months ago I decided to rewrite it in Python. Next stop C? #!/usr/bin/python &#34;&#34;&#34; twitterd Author: [...]]]></description>
			<content:encoded><![CDATA[<p>So a while ago I decided that <a href="http://char1es.net/2008/03/09/twitter-is-the-new-finger-a-bedtime-story-for-little-hackers/">twitter is the new finger</a> albeit more palitable for the masses and wrote twitterd in perl.  I&#8217;ve been using this to update my twitter and facebook status ever since.  A couple of months ago I decided to rewrite it in Python.  Next stop C?   </p>
<p><pre><code>#!/usr/bin/python
&quot;&quot;&quot;
twitterd
Author: Nathan Charles &lt;ncharles at gmail dot com&gt;
Version: 0.1
This program twits the contents of a file when it&#039;s time stamp is updated.&nbsp;&nbsp;
The functionality is similar to that of finger/.plan in days of yore.
Requires:
&nbsp;&nbsp; pytwitter
&nbsp;&nbsp; configobj
This program has no warranty to the full extent of the law
&quot;&quot;&quot;

import pytwitter
from sys import exit, argv
from os import path
from time import sleep

POLLINT = 60
READLEN = 140

def setEnv():
&nbsp;&nbsp;&nbsp;&nbsp;from configobj import ConfigObj
&nbsp;&nbsp;&nbsp;&nbsp;from os import environ
&nbsp;&nbsp;&nbsp;&nbsp;import getopt
&nbsp;&nbsp;&nbsp;&nbsp;env = {}
&nbsp;&nbsp;&nbsp;&nbsp;HOME = environ.get(&quot;HOME&quot;)
&nbsp;&nbsp;&nbsp;&nbsp;config = ConfigObj(HOME + &#039;/.twitrc&#039;)
&nbsp;&nbsp;&nbsp;&nbsp;env[&quot;watchfile&quot;] = HOME + &#039;/.plan&#039;
&nbsp;&nbsp;&nbsp;&nbsp;try:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;env[&quot;username&quot;] = config[&#039;username&#039;]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;env[&quot;password&quot;] = config[&#039;password&#039;]
&nbsp;&nbsp;&nbsp;&nbsp;except:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#.twitrc doesn&#039;t exist not nessarily a problem
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pass

&nbsp;&nbsp;&nbsp;&nbsp;try:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;env[&quot;optlist&quot;], args = getopt.getopt(argv[1:], &#039;dfh&#039;,[&quot;username=&quot;,&quot;password=&quot;])
&nbsp;&nbsp;&nbsp;&nbsp;except getopt.GetoptError:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;usage()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print &quot;called exception&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(1)
&nbsp;&nbsp;&nbsp;&nbsp;for o,a in env[&quot;optlist&quot;]:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if o == &quot;--username&quot;:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;env[&quot;username&quot;]=a
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if o == &quot;--password&quot;:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;env[&quot;password&quot;]=a

&nbsp;&nbsp;&nbsp;&nbsp;if not &quot;username&quot; in env:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print &quot;username is not set&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(1)
&nbsp;&nbsp;&nbsp;&nbsp;if not &quot;password&quot; in env:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print &quot;password is not set&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(1)
&nbsp;&nbsp;&nbsp;&nbsp;return env

def watch(username, password, watchfile):
&nbsp;&nbsp;&nbsp;&nbsp;&quot;&quot;&quot;Updates a twitter feed with the contents of a file when the timestamp is updated.
&nbsp;&nbsp;&nbsp;&nbsp;&quot;&quot;&quot;
&nbsp;&nbsp;&nbsp;&nbsp;try:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;timeStampInitial = path.getmtime(watchfile)
&nbsp;&nbsp;&nbsp;&nbsp;except:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#file doesn&#039;t exist setting to 0 because it might exist in the future
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;timeStampInitial = 0
&nbsp;&nbsp;&nbsp;&nbsp;while 1:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;timeStampIncrimented = path.getmtime(watchfile)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;except:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#file still doesn&#039;t exist
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;timeStampIncrimented = 0
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (timeStampInitial==timeStampIncrimented):
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sleep(POLLINT)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;timeStampInitial = timeStampIncrimented
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#update status
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;statusTxt = file(watchfile).read(READLEN)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;client = pytwitter.pytwitter(username=username, password=password)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rc = client.statuses_update(status=statusTxt)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print rc

def usage():
&nbsp;&nbsp;&nbsp;&nbsp;&quot;&quot;&quot;Prints when called with no arguments or with invalid arguments
&nbsp;&nbsp;&nbsp;&nbsp;&quot;&quot;&quot;
&nbsp;&nbsp;&nbsp;&nbsp;print &quot;&quot;&quot;usage: twitterd [options]
&nbsp;&nbsp; -d&nbsp;&nbsp;&nbsp;&nbsp;daemonize
&nbsp;&nbsp; -f&nbsp;&nbsp;&nbsp;&nbsp;run in forground
&nbsp;&nbsp; -h&nbsp;&nbsp;&nbsp;&nbsp;help

&nbsp;&nbsp; twitterd must have twitter username/password set. this can be set via .twitrc

&nbsp;&nbsp; --password&nbsp;&nbsp;&nbsp;&nbsp;set username
&nbsp;&nbsp; --username&nbsp;&nbsp; set password&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&quot;&quot;&quot;

if __name__ == &quot;__main__&quot;:
&nbsp;&nbsp;&nbsp;&nbsp;g = setEnv()

&nbsp;&nbsp;&nbsp;&nbsp;if g[&quot;optlist&quot;]:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for o,a in g[&quot;optlist&quot;]:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if o == &#039;-h&#039;:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;usage()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(1)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if o == &#039;-d&#039;:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#run in background
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import daemon
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;daemon.daemonize()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if o == &#039;-f&#039;:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#run in forground
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print &quot;Running in Foreground&quot;
&nbsp;&nbsp;&nbsp;&nbsp;else:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;usage()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(1)

&nbsp;&nbsp;&nbsp;&nbsp;watch(g[&quot;username&quot;], g[&quot;password&quot;], g[&quot;watchfile&quot;])</code></pre></p>
]]></content:encoded>
			<wfw:commentRss>http://char1es.net/2009/07/08/twitterd-in-python/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Low cost data logging with Arduino</title>
		<link>http://char1es.net/2009/05/24/low-cost-data-logging-with-arduino/</link>
		<comments>http://char1es.net/2009/05/24/low-cost-data-logging-with-arduino/#comments</comments>
		<pubDate>Sun, 24 May 2009 13:09:18 +0000</pubDate>
		<dc:creator>Nathan</dc:creator>
				<category><![CDATA[Code Hacking]]></category>
		<category><![CDATA[Geek out]]></category>
		<category><![CDATA[arduino]]></category>
		<category><![CDATA[temperature]]></category>
		<category><![CDATA[thermistor]]></category>

		<guid isPermaLink="false">http://char1es.net/?p=242</guid>
		<description><![CDATA[I&#8217;ve been wanting to play around with an Arduino for a while, so I bought a Duemilanove without a set goal in mind. Recently I&#8217;ve been working with Solar thermal and I needed to measure several temperatures simultaneously so decided this would be as good a project as any. I bought some &#8220;4700 ohm&#8221; thermistors [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been wanting to play around with an Arduino for a while, so I bought a <a href="http://arduino.cc/en/Main/ArduinoBoardDuemilanove">Duemilanove</a> without a set goal in mind.  Recently I&#8217;ve been working with Solar thermal and I needed to measure several temperatures simultaneously so decided this would be as good a project as any.  I bought some &#8220;4700 ohm&#8221; thermistors and hooked them up with some  other 4700 ohm resistors in a voltage divider configuration.  The output of which is hooked up to the analog inputs on the Arduino.  I found a <a href="http://www.arduino.cc/playground/ComponentLib/Thermistor">Thermistor Example</a> in the Arduino playground which I had to modify somewhat to make work with my configuration.  I was confused for about a day as to why my thermistor equation <img src='http://s.wordpress.com/latex.php?latex=T%3D%5Cfrac%7B%5Cbeta%20%7D%7B%5Cln%20%5Cleft%20%28%20%5Cfrac%7BR_%7BT%7D%7D%7BR_%7B25C%7D%7D%5Cright%20%29%2B%5Cfrac%7B%5Cbeta%7D%7B298.15%7D%7D-273.15&#038;bg=T&#038;fg=000000&#038;s=0' alt='T=\frac{\beta }{\ln \left ( \frac{R_{T}}{R_{25C}}\right )+\frac{\beta}{298.15}}-273.15' title='T=\frac{\beta }{\ln \left ( \frac{R_{T}}{R_{25C}}\right )+\frac{\beta}{298.15}}-273.15' class='latex' /> was giving me garbage.  After doubting my ablity to do math pretty severely I finally figured out that my math was indeed correct and as it turns out the &#8220;4700 ohm&#8221; thermistor package was incorrectly labeled and were actually only 470 ohm.  Anyway, I modified the code so it would work with my thermistors and pass multiple temperatures back across the serial line.  </p>
<p><a href="http://char1es.net/code/therm.pde">Arduino Thermistor Sketch</a></p>
<p>Then I wrote some quick and dirty python code to read the values coming off the serial line and write it to a csv file which I could open with OpenOffice.</p>
<p><pre><code>import serial
import time
ser = serial.Serial(&#039;/dev/tty.usbserial-A6008dxP&#039;, 9600, timeout=1)
logfile = open(&#039;test.csv&#039;, &#039;a&#039;)

while 1:&nbsp;&nbsp; # read a &#039;\n&#039; terminated line 
&nbsp;&nbsp; line = ser.readline()&nbsp;&nbsp; # read a &#039;\n&#039; terminated line
&nbsp;&nbsp; if not line:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break
&nbsp;&nbsp; words = line.split()
&nbsp;&nbsp; now = time.strftime(&quot;%d/%m/%Y %H:%M:%S&quot;, time.localtime())
&nbsp;&nbsp; a =&nbsp;&nbsp;&quot;%s, %s&quot; % (now, line)
&nbsp;&nbsp; if line.find(&#039;,&#039;) != -1:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logfile.write(a)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logfile.flush()

logfile.close()
ser.close()
</code></pre></p>
<p>The resolution isn&#8217;t that great because the inputs are only a 10bit ADCs but it&#8217;s more than enough to get trends.  Without a more accurate thermometer, I can&#8217;t tell for certain how accurate it is, but as far as I can tell it reads faster and more accurately than the mercury thermometer we have.  In university I would have done this with a fairly expensive LabVIEW system. The impressive thing is that I can get good enough information for what I need with Python and less than $30US in parts including the Arduino.  </p>
]]></content:encoded>
			<wfw:commentRss>http://char1es.net/2009/05/24/low-cost-data-logging-with-arduino/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>On the Death of Newspapers</title>
		<link>http://char1es.net/2009/03/29/on-the-death-of-newspapers/</link>
		<comments>http://char1es.net/2009/03/29/on-the-death-of-newspapers/#comments</comments>
		<pubDate>Sun, 29 Mar 2009 18:31:18 +0000</pubDate>
		<dc:creator>Nathan</dc:creator>
				<category><![CDATA[Code Hacking]]></category>
		<category><![CDATA[Ideas]]></category>
		<category><![CDATA[books]]></category>
		<category><![CDATA[LaTeX]]></category>
		<category><![CDATA[newspapers]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[RSS]]></category>

		<guid isPermaLink="false">http://char1es.net/?p=223</guid>
		<description><![CDATA[I have an old soul. At least that&#8217;s what one of my bosses at IBM told me once. He made the comment in referance to the fact that I would often bring a paper notebook to our one on one meetings instead of a laptop. I like paper, I like drawing, I like the printed [...]]]></description>
			<content:encoded><![CDATA[<p>I have an old soul.  At least that&#8217;s what one of my bosses at IBM told me once.  He made the comment in referance to the fact that I would often bring a paper notebook to our one on one meetings instead of a laptop.  I like paper, I like drawing, I like the printed page, I like books.   You can&#8217;t exactly read  Jasper Fforde or Terry Pratchett through the takeoff or landing of a plane with a laptop or a kindle.  Sometimes I&#8217;ll read a book on my laptop, but that&#8217;s only because there isn&#8217;t a physical copy handy.</p>
<p>Everybody tells me that newspapers are dying.  Which is sad.  I can&#8217;t complain too much though, because I&#8217;m the demographic that&#8217;s killing them.  I never subscribed.  Part of it was that I didn&#8217;t really like the local newspapers, (although the Independant is great and it&#8217;s free), and part of it is that I&#8217;m not a morning person and generally a little rushed in the morning.  As result most of my news comes from RSS feeds; sources such as the BBC and NY Times online editions. </p>
<p>Which brings me to my point.  I always thought it would be great if I could get a newspaper that was personalized for me.  It would aggregate my selection of news sources and simply format, print and deliver.  I&#8217;ve been sick for the last few days and spent a lot of time on my computer.  In that time I learned a bit about LaTeX, which is a way of laying out text.  Apparently it&#8217;s widely used in the academic world because it&#8217;s a way of separating formatting from content and it does professional fonts pretty well.  I hacked out a quick and dirty python program to grab an rss feed and turn it into a PDF via LaTeX.  It&#8217;s not polished but it&#8217;s a Proof of Concept.  <a href="http://char1es.net/rss2latex.py">rss2latex.py</a></p>
<p>I&#8217;m not sure I want to avocate printing off your RSS feeds everyday; it&#8217;s a waste of a lot of paper.  However I think this idea could be developed to format RSS in a more Newspaper sort of format, complete with all my web comic strips on one page!   <a href="http://www.acrylicapps.com/times/">Acrylic&#8217;s Times RSS</a> reader tries to form RSS feeds like a Newspaper, and it&#8217;s a really nice looking program, however, it doesn&#8217;t work very well with web comic strips and when it comes down to it, it&#8217;s all about the funnies.</p>
]]></content:encoded>
			<wfw:commentRss>http://char1es.net/2009/03/29/on-the-death-of-newspapers/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>twitter is the new finger (a bedtime story for little hackers)</title>
		<link>http://char1es.net/2008/03/09/twitter-is-the-new-finger-a-bedtime-story-for-little-hackers/</link>
		<comments>http://char1es.net/2008/03/09/twitter-is-the-new-finger-a-bedtime-story-for-little-hackers/#comments</comments>
		<pubDate>Mon, 10 Mar 2008 04:54:13 +0000</pubDate>
		<dc:creator>Nathan</dc:creator>
				<category><![CDATA[Babbling]]></category>
		<category><![CDATA[Code Hacking]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[stories]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://char1es.net/2008/03/09/twitter-is-the-new-finger-a-bedtime-story-for-little-hackers/</guid>
		<description><![CDATA[Once upon a time there was an operating system philosophy called Unix. Unix was the operating system of all the good people at universities and colleges. If you wanted to a use a computer at school there was only one computer to use, a Unix machine, and everybody had an account on the same Unix [...]]]></description>
			<content:encoded><![CDATA[<p>Once upon a time there was an operating system philosophy called Unix.   Unix was the operating system of all the good people at  universities and colleges.  If you wanted to a use a computer at school there was only one computer to use, a Unix machine, and everybody had an account on the same Unix server and you accessed it with a terminal.  People with accounts on the machine were called users and all your files were stored in your home directory.  The amazing thing was you never had to carry around a computer and you could get to them whenever you had access to terminal.  Unix made it easy to share, it made sure everybody was nice.   Pale men in dark rooms made sure everything worked, most of the time.  The happy little code monkeys wrote services like sendmail that allowed users to send electronic messages to each other, talk so they could chat and finger so they could see was online.   finger even checked a file in you home directory for a file called .plan that you could leave messages about what you were doing or going to be doing when you were away.   Configuration files in  Unix always had a . in front of them so you didn&#8217;t see them unless you really looked for them with ls -la .   And life was good.   Then the Personal Computer came and made it difficult to do all the things that worked well on Unix.  People had to maintain their computer and worry about nasty things like bugs, viruses, worms and blue screens of death.   Nobody used finger anymore.  And people were not happy.  Then one day the World Wide Web was invented,  people decided that they didn&#8217;t like to maintain their own data anymore so they used software on the web like gMail to store all their email.   The software code monkeys wrote things like Instant messenger so you could chat and <a href="http://twitter.com">twitter</a> so you could see what your friends were doing.    A silly little code monkey named <a href="http://char1es.net">Nathan</a> even wrote a little perl program to sync the .plan file with twitter.   So twitter was like finger.   And once again people could access their data whenever they had access to a terminal.  Except now we call terminals  apple macbook pros.  And everybody was happy except the blue screens of death.    They went and sulked under the overpasses leading away from Redmond.</p>
<p>So what is the moral of the story? Well the moral of the story is that nothing is new under the sun, and the more things change the more they stay the same.</p>
<p>Code Follows&#8230;</p>
<p><span id="more-106"></span></p>
<p>#!/usr/bin/perl<br />
#Program: twitterd<br />
#Author: Nathan Charles  ncharles at gmail dot com<br />
#Version: 0.1<br />
#This program watches .plan file in your home directory and updates<br />
#your twitter account with the contents of that file when it changes<br />
#<br />
# This program has no warranty to the full extent of the law</p>
<p>use File::Monitor;<br />
use Getopt::Long;<br />
use Net::Twitter;<br />
use POSIX &#8216;setsid&#8217;;</p>
<p>#CONSTANTS<br />
use constant TWUSER =&gt; &#8220;twitterusername&#8221;;<br />
use constant TWPASS =&gt; &#8220;twitterpassword&#8221;;<br />
use constant TWPLANINT =&gt; 60;</p>
<p>sub usage {<br />
print &#8220;usage: twitterd [-d]\n&#8221;;<br />
print &#8221;   -d, &#8211;daemon       run in background&#8221;;<br />
exit 1;<br />
}<br />
sub daemonize {<br />
open STDIN, &#8220;/dev/null&#8221;;<br />
open STDOUT,&#8221;&gt;/dev/null&#8221;;<br />
open STDERR,&#8221;&gt;/dev/null&#8221;;<br />
exit if fork &gt; 0;<br />
setsid;<br />
exec(&#8220;twitterd&#8221;);<br />
}</p>
<p>sub twitterplan {<br />
my $twit = Net::Twitter-&gt;new(username=&gt;TWUSER, password=&gt;TWPASS );<br />
open(PLAN, $file);<br />
@lines = &lt;PLAN&gt;;<br />
close(PLAN);<br />
print @lines;<br />
$result = $twit-&gt;update(@lines);<br />
print $result;<br />
}</p>
<p>sub watchloop {</p>
<p>my $loopy = 1;</p>
<p>my $monitor = File::Monitor-&gt;new();<br />
$home = $ENV{&#8216;HOME&#8217;};</p>
<p>$file = &#8220;$home/.plan&#8221;;<br />
$monitor-&gt;watch($file, \&amp;twitterplan);</p>
<p>$monitor-&gt;scan;</p>
<p>my @changes = $monitor-&gt;scan;<br />
while ($loopy )<br />
{<br />
@changes = $monitor-&gt;scan();<br />
sleep TWPLANINT<br />
}<br />
}</p>
<p>MAIN:<br />
{<br />
my $daemon = &#8221;;<br />
GetOptions (&#8216;d|daemon&#8217; =&gt; \$daemon);</p>
<p>if ($daemon) {<br />
daemonize();<br />
} else {<br />
watchloop();<br />
}<br />
}</p>
]]></content:encoded>
			<wfw:commentRss>http://char1es.net/2008/03/09/twitter-is-the-new-finger-a-bedtime-story-for-little-hackers/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>dropd.pl</title>
		<link>http://char1es.net/2007/10/09/dropdpl/</link>
		<comments>http://char1es.net/2007/10/09/dropdpl/#comments</comments>
		<pubDate>Tue, 09 Oct 2007 15:36:41 +0000</pubDate>
		<dc:creator>Nathan</dc:creator>
				<category><![CDATA[Code Hacking]]></category>
		<category><![CDATA[avahi]]></category>
		<category><![CDATA[dropcopy]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://char1es.net/wordpress/?p=100</guid>
		<description><![CDATA[Mac using Anders wanted to dump something on my laptop running Ubuntu. He suggested dropcopy but there wasn’t a server for linux. Turns out the drop copy protocol is pretty basic and it wasn’t too difficult to write a server in perl. This could be integrated into avahi so you can use bonjour. Code follows, [...]]]></description>
			<content:encoded><![CDATA[<p>Mac using <a href="http://anders.com/">Anders</a> wanted to dump something on my laptop running Ubuntu.  He suggested dropcopy but there wasn’t a server for linux.  Turns out the drop copy protocol is pretty basic and it wasn’t too difficult to write a server in perl. This could be integrated into avahi so you can use bonjour.   Code follows,</p>
<p><span id="more-100"></span><br />
#!/usr/bin/perl<br />
#Author: Nathan Charles &lt;ncharles at gmail dot com&gt;<br />
#<br />
#This is a quick and dirty DropCopy server for linux written in perl.<br />
#It dumps the file into the directory the sever is run from.<br />
#It works for me.  Your mileage may vary.<br />
#</p>
<p>use IO::Socket;<br />
print &#8220;Starting Server\n&#8221;;</p>
<p>my $SERVER_RUNNING = TRUE;</p>
<p>while($SERVER_RUNNING) {<br />
my $sock = new IO::Socket::INET (<br />
LocalHost =&gt; &#8216;localhost&#8217;,<br />
LocalPort =&gt; &#8217;5052&#8242;,<br />
Proto =&gt; &#8216;tcp&#8217;,<br />
Reuse =&gt; 1,<br />
);<br />
die &#8220;Could not create socket: $!\n&#8221; unless $sock;</p>
<p>$sock-&gt;listen();<br />
$sock-&gt;autoflush(1);<br />
my $new_sock = $sock-&gt;accept();<br />
my $HEADER_FLAG = &#8220;1&#8243;;<br />
my $header;<br />
my $filename;<br />
my $filesize;<br />
@metadata;<br />
$metacounter=0;<br />
$filesize=0;<br />
my $trans=0;</p>
<p>while(&lt;$new_sock&gt;) {<br />
if ($HEADER_FLAG) {<br />
$HEADER_FLAG=0;<br />
$headerlen= length($_);<br />
$header = substr($_,0,$headerlen-1);<br />
print $header . &#8220;\n&#8221;;<br />
$headerlen= length($_);<br />
@metadata = split(/\|/,$header);<br />
$filename = @metadata[1];<br />
$filesize = @metadata[2];<br />
print &#8220;1=&#8221;.@metadata[1].&#8221; 2=&#8221;.@metadata[2].&#8221;\n&#8221;;<br />
$_ = substr($_,$headerlen);<br />
open(FILEOUT, &#8220;&gt;&#8221;.$filename);<br />
}<br />
$trans +=length($_);<br />
print FILEOUT $_;<br />
if ($trans==$filesize) {<br />
print $trans.&#8221; Bytes of &#8220;.$filesize.&#8221; transfered.\n&#8221;;<br />
close(FILEOUT);<br />
break;<br />
}<br />
}<br />
close(FILEOUT);<br />
close($sock);<br />
}</p>
]]></content:encoded>
			<wfw:commentRss>http://char1es.net/2007/10/09/dropdpl/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>What a mess</title>
		<link>http://char1es.net/2003/09/03/what-a-mess/</link>
		<comments>http://char1es.net/2003/09/03/what-a-mess/#comments</comments>
		<pubDate>Wed, 03 Sep 2003 18:52:43 +0000</pubDate>
		<dc:creator>Nathan</dc:creator>
				<category><![CDATA[Code Hacking]]></category>

		<guid isPermaLink="false">http://char1es.net/wordpress/?p=5</guid>
		<description><![CDATA[There is no such thing as a free lunch. So I put my blog back up after having one of my servers have issues I&#8217;m poor right now. I don&#8217;t feel like spending money on a hosting service. So i host my site at several places trying to pulling togeather multiple elements in tables to [...]]]></description>
			<content:encoded><![CDATA[<p>There is no such thing as a free lunch.  So I put my blog back up after having one of my servers have issues</p>
<p>I&#8217;m poor right now.  I don&#8217;t feel like spending money on a hosting service.  So i host my site at several places trying to pulling togeather multiple elements in tables to make things work right.  One server i&#8217;ve have access to mysql one server i have access to dns,  one server i have ssh &#038; webhosting, etc. &#8230;  so thus my site is &#8220;free&#8221; but i pay in time and quality of service.  hopefully now things will be a bit more stable.</p>
]]></content:encoded>
			<wfw:commentRss>http://char1es.net/2003/09/03/what-a-mess/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
