<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title>Articles tagged meta at null program</title>
  <link rel="alternate" type="text/html"
        href="https://nullprogram.com/tags/meta/"/>
  <link rel="self" type="application/atom+xml"
        href="https://nullprogram.com/tags/meta/feed/"/>
  <updated>2026-04-07T03:24:16Z</updated>
  <id>urn:uuid:22ce0838-6736-4d87-a83f-0f86c7f1d970</id>

  <author>
    <name>Christopher Wellons</name>
    <uri>https://nullprogram.com</uri>
    <email>wellons@nullprogram.com</email>
  </author>

  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  <entry>
    <title>Inspiration from Data-dependent Rotations</title>
    <link rel="alternate" type="text/html" href="https://nullprogram.com/blog/2018/02/07/"/>
    <id>urn:uuid:917b72f1-3aad-3af3-075a-a4b0a6eb8a4d</id>
    <updated>2018-02-07T23:59:59Z</updated>
    <category term="c"/><category term="crypto"/><category term="meta"/>
    <content type="html">
      <![CDATA[<p>This article is an expanded email I wrote in response to a question
from Frank Muller. He asked how I arrived at my solution to a
<a href="/blog/2017/10/06/">branchless UTF-8 decoder</a>:</p>

<blockquote>
  <p>I mean, when you started, I’m pretty the initial solution was using
branches, right? Then, you’ve applied some techniques to eliminate
them.</p>
</blockquote>

<p>A bottom-up approach that begins with branches and then proceeds to
eliminate them one at a time sounds like a plausible story. However,
this story is the inverse of how it actually played out. It began when I
noticed a branchless decoder could probably be done, then I put together
the pieces one at a time without introducing any branches. But what
sparked that initial idea?</p>

<p>The two prior posts reveal my train of thought at the time: <a href="/blog/2017/09/15/">a look at
the Blowfish cipher</a> and <a href="/blog/2017/09/21/">a 64-bit PRNG shootout</a>. My
layman’s study of Blowfish was actually part of an examination of a
number of different block ciphers. For example, I also read the NSA’s
<a href="http://eprint.iacr.org/2013/404.pdf">Speck and Simon paper</a> and then <a href="https://github.com/skeeto/scratch/tree/master/speck">implemented the 128/128 variant
of Speck</a> — a 128-bit key and 128-bit block. I didn’t take the
time to write an article about it, but note how the entire cipher —
key schedule, encryption, and decryption — is just 40 lines of code:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">struct</span> <span class="n">speck</span> <span class="p">{</span>
    <span class="kt">uint64_t</span> <span class="n">k</span><span class="p">[</span><span class="mi">32</span><span class="p">];</span>
<span class="p">};</span>

<span class="kt">void</span>
<span class="nf">speck_init</span><span class="p">(</span><span class="k">struct</span> <span class="n">speck</span> <span class="o">*</span><span class="n">ctx</span><span class="p">,</span> <span class="kt">uint64_t</span> <span class="n">x</span><span class="p">,</span> <span class="kt">uint64_t</span> <span class="n">y</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">k</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">y</span><span class="p">;</span>
    <span class="k">for</span> <span class="p">(</span><span class="kt">uint64_t</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">31</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">x</span> <span class="o">=</span> <span class="p">(</span><span class="n">x</span> <span class="o">&gt;&gt;</span> <span class="mi">8</span><span class="p">)</span> <span class="o">|</span> <span class="p">(</span><span class="n">x</span> <span class="o">&lt;&lt;</span> <span class="mi">56</span><span class="p">);</span>
        <span class="n">x</span> <span class="o">+=</span> <span class="n">y</span><span class="p">;</span>
        <span class="n">x</span> <span class="o">^=</span> <span class="n">i</span><span class="p">;</span>
        <span class="n">y</span> <span class="o">=</span> <span class="p">(</span><span class="n">y</span> <span class="o">&lt;&lt;</span> <span class="mi">3</span><span class="p">)</span> <span class="o">|</span> <span class="p">(</span><span class="n">y</span> <span class="o">&gt;&gt;</span> <span class="mi">61</span><span class="p">);</span>
        <span class="n">y</span> <span class="o">^=</span> <span class="n">x</span><span class="p">;</span>
        <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">k</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">y</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="kt">void</span>
<span class="nf">speck_encrypt</span><span class="p">(</span><span class="k">const</span> <span class="k">struct</span> <span class="n">speck</span> <span class="o">*</span><span class="n">ctx</span><span class="p">,</span> <span class="kt">uint64_t</span> <span class="o">*</span><span class="n">x</span><span class="p">,</span> <span class="kt">uint64_t</span> <span class="o">*</span><span class="n">y</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">32</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
        <span class="o">*</span><span class="n">x</span> <span class="o">=</span> <span class="p">(</span><span class="o">*</span><span class="n">x</span> <span class="o">&gt;&gt;</span> <span class="mi">8</span><span class="p">)</span> <span class="o">|</span> <span class="p">(</span><span class="o">*</span><span class="n">x</span> <span class="o">&lt;&lt;</span> <span class="mi">56</span><span class="p">);</span>
        <span class="o">*</span><span class="n">x</span> <span class="o">+=</span> <span class="o">*</span><span class="n">y</span><span class="p">;</span>
        <span class="o">*</span><span class="n">x</span> <span class="o">^=</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">k</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
        <span class="o">*</span><span class="n">y</span> <span class="o">=</span> <span class="p">(</span><span class="o">*</span><span class="n">y</span> <span class="o">&lt;&lt;</span> <span class="mi">3</span><span class="p">)</span> <span class="o">|</span> <span class="p">(</span><span class="o">*</span><span class="n">y</span> <span class="o">&gt;&gt;</span> <span class="mi">61</span><span class="p">);</span>
        <span class="o">*</span><span class="n">y</span> <span class="o">^=</span> <span class="o">*</span><span class="n">x</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="k">static</span> <span class="kt">void</span>
<span class="nf">speck_decrypt</span><span class="p">(</span><span class="k">const</span> <span class="k">struct</span> <span class="n">speck</span> <span class="o">*</span><span class="n">ctx</span><span class="p">,</span> <span class="kt">uint64_t</span> <span class="o">*</span><span class="n">x</span><span class="p">,</span> <span class="kt">uint64_t</span> <span class="o">*</span><span class="n">y</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">32</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
        <span class="o">*</span><span class="n">y</span> <span class="o">^=</span> <span class="o">*</span><span class="n">x</span><span class="p">;</span>
        <span class="o">*</span><span class="n">y</span> <span class="o">=</span> <span class="p">(</span><span class="o">*</span><span class="n">y</span> <span class="o">&gt;&gt;</span> <span class="mi">3</span><span class="p">)</span> <span class="o">|</span> <span class="p">(</span><span class="o">*</span><span class="n">y</span> <span class="o">&lt;&lt;</span> <span class="mi">61</span><span class="p">);</span>
        <span class="o">*</span><span class="n">x</span> <span class="o">^=</span> <span class="n">ctx</span><span class="o">-&gt;</span><span class="n">k</span><span class="p">[</span><span class="mi">31</span> <span class="o">-</span> <span class="n">i</span><span class="p">];</span>
        <span class="o">*</span><span class="n">x</span> <span class="o">-=</span> <span class="o">*</span><span class="n">y</span><span class="p">;</span>
        <span class="o">*</span><span class="n">x</span> <span class="o">=</span> <span class="p">(</span><span class="o">*</span><span class="n">x</span> <span class="o">&lt;&lt;</span> <span class="mi">8</span><span class="p">)</span> <span class="o">|</span> <span class="p">(</span><span class="o">*</span><span class="n">x</span> <span class="o">&gt;&gt;</span> <span class="mi">56</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Isn’t that just beautiful? It’s so tiny and fast. Other than the
not-very-arbitrary selection of 32 rounds, and the use of 3-bit and
8-bit rotations, there are no magic values. One could fairly
reasonably commit this cipher to memory if necessary, similar to the
late RC4. Speck is probably my favorite block cipher right now,
<em>except</em> that I couldn’t figure out the key schedule for any of the
other key/block size variants.</p>

<p>Another cipher I studied, though in less depth, was <a href="http://people.csail.mit.edu/rivest/Rivest-rc5rev.pdf">RC5</a> (1994),
a block cipher by (obviously) Ron Rivest. The most novel part of RC5
is its use of data dependent rotations. This was a very deliberate
decision, and the paper makes this clear:</p>

<blockquote>
  <p>RC5 should <em>highlight the use of data-dependent rotations</em>, and
encourage the assessment of the cryptographic strength data-dependent
rotations can provide.</p>
</blockquote>

<p>What’s a data-dependent rotation. In the Speck cipher shown above,
notice how the right-hand side of all the rotation operations is a
constant (3, 8, 56, and 61). Suppose that these operands were not
constant, instead they were based on some part of the value of the
block:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    <span class="kt">int</span> <span class="n">r</span> <span class="o">=</span> <span class="o">*</span><span class="n">y</span> <span class="o">&amp;</span> <span class="mh">0x0f</span><span class="p">;</span>
    <span class="o">*</span><span class="n">x</span> <span class="o">=</span> <span class="p">(</span><span class="o">*</span><span class="n">x</span> <span class="o">&gt;&gt;</span> <span class="n">r</span><span class="p">)</span> <span class="o">|</span> <span class="p">(</span><span class="o">*</span><span class="n">x</span> <span class="o">&lt;&lt;</span> <span class="p">(</span><span class="mi">64</span> <span class="o">-</span> <span class="n">r</span><span class="p">));</span>
</code></pre></div></div>

<p>Such “random” rotations “frustrate differential cryptanalysis” according
to the paper, increasing the strength of the cipher.</p>

<p>Another algorithm that uses data-dependent shift is the <a href="http://www.pcg-random.org/">PCG family of
PRNGs</a>. Honestly, the data-dependent “permutation” shift is <em>the</em>
defining characteristic of PCG. As a reminder, here’s the simplified PCG
from my shootout:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">uint32_t</span>
<span class="nf">spcg32</span><span class="p">(</span><span class="kt">uint64_t</span> <span class="n">s</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
<span class="p">{</span>
    <span class="kt">uint64_t</span> <span class="n">m</span> <span class="o">=</span> <span class="mh">0x9b60933458e17d7d</span><span class="p">;</span>
    <span class="kt">uint64_t</span> <span class="n">a</span> <span class="o">=</span> <span class="mh">0xd737232eeccdf7ed</span><span class="p">;</span>
    <span class="o">*</span><span class="n">s</span> <span class="o">=</span> <span class="o">*</span><span class="n">s</span> <span class="o">*</span> <span class="n">m</span> <span class="o">+</span> <span class="n">a</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">shift</span> <span class="o">=</span> <span class="mi">29</span> <span class="o">-</span> <span class="p">(</span><span class="o">*</span><span class="n">s</span> <span class="o">&gt;&gt;</span> <span class="mi">61</span><span class="p">);</span>
    <span class="k">return</span> <span class="o">*</span><span class="n">s</span> <span class="o">&gt;&gt;</span> <span class="n">shift</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Notice how the final shift depends on the high order bits of the PRNG
state. (This one weird trick from Melissa O’Neil will significantly
improve your PRNG. Xorshift experts hate her.)</p>

<p>I think this raises a really interesting question: Why did it take until
2014 for someone to apply a data-dependent shift to a PRNG? Similarly,
why are <a href="https://crypto.stackexchange.com/q/20325">data-dependent rotations not used in many ciphers</a>?</p>

<p>My own theory is that this is because many older instruction set
architectures can’t perform data-dependent shift operations efficiently.</p>

<p>Many instruction sets only have a fixed shift (e.g. 1-bit), or can
only shift by an immediate (e.g. a constant). In these cases, a
data-dependent shift would require a loop. These loops would be a ripe
source of side channel attacks in ciphers due to the difficultly of
making them operate in constant time. It would also be relatively slow
for video game PRNGs, which often needed to run on constrained
hardware with limited instruction sets. For example, the 6502 (Atari,
Apple II, NES, Commodore 64) and the Z80 (too many to list) can only
shift/rotate one bit at a time.</p>

<p>Even on an architecture with an instruction for data-dependent shifts,
such as the x86, those shifts will be slower than constant shifts, at
least in part due to the additional data dependency.</p>

<p>It turns out there are also some patent issues (ex. <a href="https://www.google.com/patents/US5724428">1</a>, <a href="https://www.google.com/patents/US6269163">2</a>).
Fortunately most of these patents have now expired, and one in
particular is set to expire this June. I still like my theory better.</p>

<h3 id="to-branchless-decoding">To branchless decoding</h3>

<p>So I was thinking about data-dependent shifts, and I had also noticed I
could trivially check the length of a UTF-8 code point using a small
lookup table — the first step in my decoder. What if I combined these: a
data-dependent shift based on a table lookup. This would become the last
step in my decoder. The idea for a branchless UTF-8 decoder was
essentially borne out of connecting these two thoughts, and then filling
in the middle.</p>

]]>
    </content>
  </entry>
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  <entry>
    <title>Ten Years of Blogging</title>
    <link rel="alternate" type="text/html" href="https://nullprogram.com/blog/2017/09/01/"/>
    <id>urn:uuid:17953fb0-0161-343b-5bc6-7a569cedb128</id>
    <updated>2017-09-01T03:47:36Z</updated>
    <category term="rant"/><category term="meta"/>
    <content type="html">
      <![CDATA[<p>As of today, I’ve been blogging for 10 years. In this time I’ve written
302,000 words across <a href="/index/">343 articles</a> — a rate of one article every
week and a half. These articles form a record of my professional
progress, touching on both “hard” technical skills and “soft”
communication skills. My older articles are a personal reminder of how
far I’ve come. They are proof that I’m not as stagnant as I sometimes
feel, and it helps me to sympathize with others who are currently in
those earlier stages of their own career.</p>

<p>That index where you can find these 343 articles is sorted
newest-first, because it correlates with best-first. It’s a trend I
hope to continue.</p>

<h3 id="history">History</h3>

<p>Before blogging, I had a simple Penn State student page showcasing a
few small — and, in retrospect, trivial — side projects (<a href="https://github.com/skeeto/pngarch">1</a>,
<a href="https://github.com/skeeto/binitools">2</a>, <a href="https://github.com/skeeto/mandelbrot">3</a>), none of which went anywhere. Around the beginning
of my final semester of college, I was inspired by Mark Dominus’ <a href="https://blog.plover.com/">The
Universe of Discourse</a> and Andy Owen’s <a href="http://web.archive.org/web/20110608003905/http://ultra-premium.com/b/">Friendly Robot
Overlord</a> (gone since 2011) to start my own <a href="http://blosxom.sourceforge.net/">blosxom</a>
blog. It would be an outlet to actively discuss my projects. Some time
later GitHub was founded, and I <a href="/blog/2011/08/05/">switched to a static blog</a>
hosted by <a href="https://pages.github.com/">GitHub Pages</a>, which is where it lives to this day.</p>

<p>It’s been more challenging to manage all this content than I ever
anticipated. It’s like maintaining a large piece of software, except
it’s naturally more fragile. Any time I make a non-trivial change to
the CSS, I have to inspect the archives to check if I broke older
articles. If I did, sometimes it’s a matter of further adjusting the
CSS. Other times I’ll mass edit a couple hundred articles in order to
normalize some particular aspect, such as heading consistency or image
usage. (Running a macro over an Emacs’ <a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Dired.html">Dired</a> buffer is great
for this.)</p>

<p>I decided in those early days to Capitalize Every Word of the
Title, and I’ve stuck with this convention purely out of
consistency even though it’s looked weird to me for years. I don’t
want to edit the old titles, and any hard changeover date would be
even weirder (in the index listing).</p>

<p>With more foresight and experience, I could have laid down better
conventions for myself from the beginning. Besides the universal
impossibility of already having experience before it’s needed, there’s
also the issue that the internet’s conventions have changed, too. This
blog is currently built with HTML5, but this wasn’t always the case —
especially considering that predates HTML5. When <a href="/blog/2009/06/30/">I switched to
HTML5</a>, I also adjusted some of my own conventions to match,
since, at the time, I was still writing articles in raw HTML.</p>

<p>The mobile revolution also arrived since starting this blog. Today,
about one third of visitors read the blog from a mobile device. I’ve
also adjusted the CSS to work well on these devices. To that third of
you: I hope you’re enjoying the experience!</p>

<p>Just in case you haven’t tried it, the blog also works really well with
terminal-based browsers, such as Lynx and ELinks. Go ahead and give it a
shot. The header that normally appears at the top of the page is
actually at the bottom of the HTML document structure. It’s out of the
way for browsers that ignore CSS.</p>

<p>If that’s not enough, last year I also spent effort making the printed
style of my articles look nice. Take a look at the printed version of
this article (i.e. print preview, print to PDF), and make sure to turn
off the little headers added by the browser. A media selector provides
a separate print stylesheet. Chrome / Chromium has consistently had
the best results, followed by Firefox. Someday I’d like for browsers
to be useful as typesetting engines for static documents — as an
alternative to LaTeX and Groff — but they’ve still got a ways to go
with paged media. (Trust me, I’ve tried.)</p>

<p>With more foresight, I could have done something better with my
permanent URLs. Notice how they’re just dates and don’t include the
title. URLs work better when they include human-meaningful context.
Ideally I should be able to look at any one of my URLs and know what
it’s about. Again, this decision goes all the way back to those early
days when I first configured blosxom, not knowing any better.</p>

<p><a href="https://www.w3.org/Provider/Style/URI">URLs are forever</a>, and I don’t want to break all my old links.
Consistency is better than any sort of correction. I’m also practically
limited to one article per day, though this has never been a real
problem.</p>

<h3 id="motivation">Motivation</h3>

<p>For me, an important motivation for writing is to say something unique
about a topic. For example, I’m not interested in writing a tutorial
unless either no such tutorial already exists, or there’s some vital
aspect all the existing tutorials miss. Each article should add new
information to the internet, either raw information or through
assembling existing information in a new way or with a unique
perspective.</p>

<p>I also almost constantly feel like I’m behind the curve, like I don’t
know enough or I don’t have enough skill. As many of you know, the
internet is really effective at causing these feelings. Every day lots
of talented people are sharing interesting and complicated things
across all sorts of topics. For topics that overlap my own desired
expertise, those projects have me thinking, “Man, I have <em>no idea</em> how
to even start doing that. There’s so much I don’t know, and so much
more I need to learn.” Writing articles as I learn is a great way to
keep on top of new subjects.</p>

<p>This is tied to another problem: I have a tendency to assume the
things I’ve known for awhile are common knowledge. This shows up in a
few ways. First, if everyone knows what I know, plus they know a bunch
of things that I don’t know, then I’ve got a lot of catching up to do.
That’s another source of feeling behind the curve.</p>

<p>Second, when writing an article on a topic where I’ve got years of
experience, I leave out way too many important details, assuming the
reader already knows them. When an article I regard as valuable gets a
weak response, it’s probably related to this issue.</p>

<p>Third, after <a href="/blog/2016/09/02/">three years of teaching</a>, it seems like it’s
becoming more difficult to put myself in the student’s shoes. I’m
increasingly further away from my own days learning those early topics,
and it’s harder to remember the limitations of my knowledge at that
time. Having this blog really helps, and I’ve re-read some of my older
articles to recall my mindset at the time.</p>

<p>Another way the blog helps is that it’s like having my own textbook.
When teaching a topic to someone — and not necessarily a formal mentee
— or even when just having a discussion, I will reference my articles
when appropriate. Since they’re designed to say something unique, my
article may be the only place to find certain information in a
conveniently packaged form.</p>

<p>Finally, the last important motivating factor is that I want to
<a href="http://slatestarcodex.com/2016/07/25/how-the-west-was-won/">spread my preferred memes</a>. <em>Obviously</em> the way I do things is
the Right Way, and the people who do things differently (the Wrong
Way) are stupid and wrong. By writing about the sorts of topics and
technologies I enjoy — C, low-level design, Emacs, Vim, programming on
unix-like systems, my personal programming style — I’m encouraging
others to follow my lead. Surely I’m responsible for at least one
Emacs convert out there!</p>

<h3 id="formal-professional-writing">“Formal” professional writing</h3>

<p>Despite having three or four novels worth of (mostly) technical writing
here, my formal workplace writing leaves much to be desired. I’m no
standout in this area. In the same period of time I’ve written just a
handful of formal memos, each about the same length as a long blog post.</p>

<p>Why so few? These memos are <em>painful</em> to write. In order to be
officially recognized, the formal memo process must be imposed upon
me. What this means is that, compared to a blog post, these memos take
at least an order of magnitude longer to write.</p>

<p>The process involves more people, dragged out over a long period of
time. The writing is a lot less personal, which, in my opinion, makes it
drier and less enjoyable. After the initial draft is complete, I have to
switch to vastly inferior tools: emailing the same Microsoft Office
documents back and forth between various people, without any proper
source control. The official, mandated memo template was created by
someone who didn’t know how to effectively operate a word processor, who
had a poor sense of taste (ALL CAPS HEADINGS), and who obviously had no
training in typesetting or style.</p>

<p>At the end of this long process, it’s filed into a system with no
practical search capability, and where it will be quietly purged after
five years, never to be seen again. Outside of the reviewers who were
directly involved in the memo process, somewhere between zero and two
people will have actually read it. Literally.</p>

<p>Arguably the memo might more polished than a blog post. I’m skeptical of
this, but suppose that’s true. I’d still <em>much</em> rather have written ten
less-polished blog posts than one more-polished memo. That’s also ten
shots to produce, by chance, a more valuable article than the single,
precious memo.</p>

<p>Let’s broaden the scope to academic papers. Thanks to some great
co-workers — all three of whom are smarter and handsomer than me — a
year ago I finally got a published academic paper under my belt (and
more to come): <a href="https://skeeto.s3.amazonaws.com/share/p15-coffman.pdf"><em>ROP Gadget Prevalence and Survival under
Compiler-based Binary Diversification Schemes</em></a> (and I said
<em>memos</em> were dry!). A ton of work went into this paper, and it’s far
more substantial than any memo or single blog post. The process was a
lot more pleasant (LaTeX instead of Word), and the results are
definitely much more polished than a typical blog post. It reads well
and has interesting information to present.</p>

<p>This all sounds great until you consider the impact. According to
ACM’s statistics, the paper has been accessed 130 times as of this
writing. (Yes, providing an unofficial link to the paper like I just
did above doesn’t help, but I ran out of those crappy “free” links.
Sue me.) Sure, the PDF might have been passed around in untrackable
ways, but I also bet a lot of those accesses were just downloads that
were never read. So let’s split the difference and <strong>estimate around
130 people read it</strong>.</p>

<p>What kind of impact does a blog post have? Talking about these numbers
feels a bit taboo, like discussing salaries, but it’s important for the
point I’m about to make.</p>

<ul>
  <li>July 2017: <a href="/blog/2017/07/02/">Rolling Shutter Simulation in C</a>
    <ul>
      <li>10,400 unique visitors</li>
      <li>#22 most popular</li>
    </ul>
  </li>
  <li>August 2017: <a href="/blog/2017/08/20/">A Tutorial on Portable Makefiles</a>
    <ul>
      <li>14,300 unique visitors</li>
      <li>#16 most popular</li>
    </ul>
  </li>
  <li>June 2017: <a href="/blog/2017/06/15/">Switching to the Mutt Email Client</a>
    <ul>
      <li>23,100 unique visitors</li>
      <li>#5 most popular</li>
    </ul>
  </li>
  <li>May 2015: <a href="/blog/2015/05/15/">Raw Linux Threads via System Calls</a>
    <ul>
      <li>40,500 unique visitors</li>
      <li>#1 most popular, not even counting the Japanese publication</li>
    </ul>
  </li>
</ul>

<p>Note that all but the last has been published for less time than our
paper. The average time on these pages is between 5 and 6 minutes, so
these are actual readers, not just visitors that take one glance and
leave. Thanks to the information age, <strong>a technical blog article on
established blog can reach an audience 100 times larger than a journal
for a fraction of the effort and cost</strong>. There are other benefits, too:</p>

<ol>
  <li>
    <p>I get immediate feedback in the form of comments and email (<em>open
peer review</em>).</p>
  </li>
  <li>
    <p>The content is available for free (<em>open access</em>). It’s trivial to
link and share blog articles.</p>
  </li>
  <li>
    <p>Even more, this entire blog is in the public domain. If you don’t
believe me, check out the public domain dedication in the footer of
this page. It’s been there for years, and you can <a href="https://github.com/skeeto/skeeto.github.com">verify that
yourself</a>. Every single change to this blog in the past 6 years
has been publicly documented (<em>transparency</em>).</p>
  </li>
  <li>
    <p>When I write about a topic, I make it a goal to provide the code and
data to try it for yourself (<em>open data and materials</em>). This code
and data is also either in the public domain, or as close to it as
possible.</p>
  </li>
  <li>
    <p>Link aggregators and social media are great at finding the best stuff
and making it more visible (<em>censorship resistance</em>). When I have a
big hit, it’s often Reddit or Hacker News driving people to my
article. Sometimes it’s other blogs.</p>
  </li>
</ol>

<p>In 2017, a blog is by far the most effective way to publish and share
written information, and <a href="http://daniellakens.blogspot.com/2017/04/five-reasons-blog-posts-are-of-higher.html">have more scientific quality than
journals</a>. More people should be publishing through blog
articles than traditional forms of publications, which are far less
effective.</p>

<p>Since this has proven to be such an effective medium, I’m going to
make a promise right here, right now. And as I explained above with
transparency, there are no take-backs on this one. If you’re reading
this, it’s on the public record forever. <strong>I promise to deliver
another 10 years of free, interesting, useful content.</strong> This stuff is
going to be even better, too. On this blog’s 20th anniversary,
September 1st, 2027, we’ll see how I did.</p>

]]>
    </content>
  </entry>
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  <entry>
    <title>Tag Feeds for null program</title>
    <link rel="alternate" type="text/html" href="https://nullprogram.com/blog/2014/06/08/"/>
    <id>urn:uuid:f47e5404-cc4a-3cc0-01ce-a844c04721b8</id>
    <updated>2014-06-08T05:53:46Z</updated>
    <category term="meta"/><category term="rant"/>
    <content type="html">
      <![CDATA[<p>I just added a <a href="/tags/">formal tags page</a> along with individual feeds
for each tag. I’ve had tags for a couple of years now, but they were
really only useful for traveling sideways to similar articles. So now,
if you’re only interested in a subset of my content, you can subscribe
to one or more tags rather than the main Atom feed.</p>

<p>What prompted this? In <a href="/blog/2014/06/04/">my <em>Emacs Chat</em></a>, Sacha asked me if this
blog was part of <a href="http://planet.emacsen.org/">Planet Emacsen</a> (currently, it’s not). If
my tags are accurate, only about 25% of my articles are about Emacs,
so most of my blog isn’t relevant there. Tag feeds will go a long way
to help support these “planet” aggregators, should they want to
include my articles. For example, Planet Emacsen would use <a href="/tags/emacs/feed/">my Emacs
feed</a>.</p>

<h3 id="static-site-generation">Static Site Generation</h3>

<p>I couldn’t practically support these extra feeds until recently.
Remember, this blog <a href="/blog/2011/08/05/">is statically generated</a>. More feeds means
more content to generate, because articles are duplicated in whole for
each feed. In past years, Jekyll would probably take on the order of
an hour to do all this for a single build. Fortunately, Jekyll has
improved dramatically, especially in the past year or so, and these
feeds have little impact on the total build time. It’s currently
around 10 seconds or so. Not bad at all!</p>

<p>A consequence of being statically generated is that you can’t ask for
a combination of tags as a single feed. It would be a combinatorial
nightmare (billions of feeds). Plus, the request would have to
normalize the tag order (e.g. alphabetical) or else the combinatorial
explosion to be far worse (i.e. exceeding the number of atoms in the
universe). So I hope you can forgive me when subscribing to each tag
individually.</p>

<h3 id="duplicate-articles">Duplicate Articles</h3>

<p>What if an article matches multiple tags? It will appear in each feed
where it’s tagged, possibly showing up multiple times in your web feed
reader. Fortunately, this is where Atom saves the day! I’m leveraging
Atom’s prudent design to make this work cleanly. Articles’ UUIDs are
consistent across all of these feeds, so if your web feed reader is
smart enough, it will recognize these as being the same article. For
example, this article is <code class="language-plaintext highlighter-rouge">f47e5404-cc4a-3cc0-01ce-a844c04721b8</code> regardless of which feed
you see it in.</p>

<p>Unfortunately, <a href="/blog/2013/09/04/">Elfeed</a> isn’t smart enough for this. Sorry! In
order to better support all the broken RSS feeds out there, <a href="/blog/2013/09/09/">I had to
compromise on entry keying</a>. I couldn’t trust RSS feeds to provide
me a reasonably unique key, so, transitively, Elfeed doesn’t fully
trust Atom’s UUIDs either. These RSS feeds are broken largely because
<a href="/blog/2013/09/23/">RSS itself is a broken mess</a>. When making new feeds in the
future, please use Atom!</p>

<p>Atom <em>requires</em> that every feed and article have a proper UUID. It
doesn’t matter where you get the feed from. You could subscribe to the
same exact feed at three different URLs (mirrors perhaps) and your
reader could reliably use the UUIDs to avoid duplication. Or, if
you’re subscribed to an aggregator like Planet Emacsen, and it
includes content from a feed to which you’re also directly subscribed,
your reader client should be able to merge these articles. In
comparison, RSS not only doesn’t require UUIDs, it actively
discourages them with its broken <code class="language-plaintext highlighter-rouge">guid</code> tag, so merging content from
multiple sources is impossible with RSS.</p>

<p>Anyway, if most of my content doesn’t suit you, you can now subscribe
to the subset that does. Aren’t Atom feeds cool?</p>

]]>
    </content>
  </entry>
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  <entry>
    <title>Moved To New Hosting</title>
    <link rel="alternate" type="text/html" href="https://nullprogram.com/blog/2011/08/05/"/>
    <id>urn:uuid:40abf691-72c5-3686-770f-220b858eebc9</id>
    <updated>2011-08-05T00:00:00Z</updated>
    <category term="git"/><category term="meta"/>
    <content type="html">
      <![CDATA[<p>If you see this post, then you’re receiving null program from its new
host: <a href="https://github.com/">GitHub</a>. The end of the month marks 4 years of my blog
(the last such announcement was <a href="/blog/2009/09/01/">two years ago</a>), and what was
going to be the 2-year renewal with my old host. I took the
opportunity to reassess my hosting situation and reorganize my
back-end.</p>

<p>The repository that houses my entire blog is here,</p>

<ul>
  <li><a href="https://github.com/skeeto/skeeto.github.com">https://github.com/skeeto/skeeto.github.com</a></li>
</ul>

<p>You can run an entirely local version of my blog from that repository.
You could also make corrections, commit them, and give me a pull
request — not that I’m expecting that to happen.</p>

<p>Initially I considered going in the opposite direction. I looked into
renting out a VM, rebuilding my site from scratch as a Java Servlet,
and hosting it from the VM. That would double my monthly costs, but
give me a cool new thing to play with. It would also be a lot of work
building a back-end from scratch.</p>

<p>Ultimately I wanted to work entirely within Git. I wanted to write a
new post on my local machine, view it using a local web server, and,
when I was satisfied, commit it and push it as a commit to the real
server. My old situation had me checking out new posts by posting them
live on the real server. I didn’t like that.</p>

<p>I eventually discovered <a href="http://pages.github.com/">GitHub Pages</a>. GitHub will host your
static content for free. Not only that, but they’ll process it with
<a href="https://github.com/mojombo/jekyll">Jekyll</a>. That means I can push “source” files to GitHub and
they’ll “compile” them into my website for me. My blog is very
well-suited for static hosting, so this is everything I needed. And
the price is right: this is a free service!</p>

<p>Going back through each of my old posts, refitting them for Jekyll,
was a very time consuming process. Every video, image, and highlighted
bit of source code needed to be reworked. In addition to moving them
into place for Jekyll, I improved the organization of my videos and
images. At my old host, I highlighted source code with the
<a href="/blog/2009/04/23/">htmlize</a> Emacs extension. Jekyll has a much nicer solution:
<a href="http://pygments.org/">Pygments</a>. However, this required stripping away all of the
htmlize HTML code, reversing all of the HTML entities, and placing the
Pygments delimiters; this was a process that couldn’t be automated
because it required a lot of human judgment.</p>

<p>One thing I did notice from reworking all my source code samples,
particularly more recent entries, was that most of my in-line code is
Lisp! Common Lisp syntax highlighting was the most common, though it
was really highlighting Elisp. My very early posts are dominated by
Octave syntax highlighting.</p>

<p>Due to static hosting, for comments I went to <a href="http://disqus.com/">Disqus</a>. It was
very easy and painless to integrate into my static blog. Unfortunately
I haven’t yet looked into the import/export situation with my old
comments. It looks like it should be possible to do. I can export to
the WordPress XML format and import them into Disqus.</p>

<p><em>Update: I have now imported all of the old comments. The process went
very smoothly and took very little effort on my part, since I had
already been storing exactly the right information in the right form.</em></p>

<p>For comments, I actually considered the pull request thing. If you
wanted to leave a comment, you would clone my blog’s repository, edit
in a comment, and ask me to pull in your change. That’s a very large
barrier to commenting, and I doubt anyone would do it, so I skipped
that idea.</p>

<p>So this is my new blog situation. I’ve completely moved away from
blosxom now. I trimmed some fat in the transition, so it currently
weighs in at about 128MB. I’d like to keep it under 300MB, but that’s
not overly important. Hopefully you can’t really tell the difference
between the new and the old. The RSS feed is in the same place, so you
don’t need to change anything to keep following. I did break my
“short” and “long” permalinks but no one was using them anyway. Even
though I’m now using GitHub, I’m not actually too dependent on
them. My transformation to Jekyll gives me more freedom than ever. I
could very easily move to any host at this point.</p>

]]>
    </content>
  </entry>
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  <entry>
    <title>Comments Upgrade with Avatars</title>
    <link rel="alternate" type="text/html" href="https://nullprogram.com/blog/2009/10/10/"/>
    <id>urn:uuid:3de1f1d8-9649-38b9-4efe-b3f7a0f731ad</id>
    <updated>2009-10-10T00:00:00Z</updated>
    <category term="meta"/>
    <content type="html">
      <![CDATA[<!-- 10 October 2009 -->
<p class="abstract">
Update: This is refering to my old, hand-written comment system,
before I changed web hosts and switched to external comment hosting.
</p>
<p>
I started getting Asian spam in my comments in the last couple
days. If you are subscribed to the comments feed you probably noticed
this. The spammer was manually filling out captchas, so this wasn't a
bot but rather a patient human being. Getting tired of removing these,
I set up some filters to silently drop messages that fit certain
criteria. By "silently" I mean the server tells the client everything
went fine but the comment never actually gets written to the database.
</p>
<p>
The spammer gained nothing except annoying us because all links in
comments get a <code>rel="nofollow"</code> attribute, which tells
search engines to ignore it. That, plus small readership and
captcha-solving gives little incentive for spamming.
</p>
<p>
Well anyway, while I had my sleeves rolled up and my hands on the code
I decided to make some upgrades I have been wanting to do. The e-mail
address is no longer displayed (stupid idea in the first place) but
instead used for a <a href="http://en.gravatar.com/">Gravatar</a>
image. You can also specify a home URL, which will be linked from your
name. This makes my comment system work very similarly to what you
find around the web, except that I don't require anything from you but
a captcha and a comment.
</p>
<p>
I also fixed a small usability issue: when you preview a comment now
it takes you right down to the form rather than leaving you at the top
of the page. The back-end database was also adjusted from the original
pollxn design to scale better as the website grows.
</p>
<p>
Now, Gravatar is a neat concept but I have two complaints. One, I
don't like centralized systems. It's a single point of failure and a
single point of control. It has privacy issues. It's anti-web. It's
inelegant. Decentralized systems built around self-enforcing protocols
are more robust and democratic.
</p>
<p>
Luckily, a decentralized version does exist! It's a specification
called <a href="http://pavatar.com/">Pavatar</a>. The avatar is tied
to a URL rather than an e-mail address. However, it's a bit less
flexible, since it needs to remain simple on the server side. It's
harder to set up and I doubt 99% of the users on the web would be
capable of doing it. What would help Pavatar gain a wider audience
would be Pavatar provider services. Hmmm...
</p>
<p>
So, I think might switch it to Pavatar sometime, with a possible
fall-back to Gravatar. That takes significantly more work to set up
than Gravatar does, so it's a future project. And, well, no one uses
it yet either. I actually thought the project was dead until just now
because their website was down the first time I visited it a couple
months ago.
</p>
<p>
My second complaint is that Gravatar incorrectly assumes e-mail
addresses are not case-sensitive. The domain part is, but the alias
part is not. These two addresses could technically arrive to two
different e-mail inboxes,
</p>
<pre>
chris@example.com
Chris@example.com
</pre>
<p>
Pretty much every e-mail server will treat these as the same address
as a convenience, because treating these differently would just be
confusing, but it's not necessarily the case. Gravatar specifically
says to hash the e-mail in lowercase form, so the unique address
<code>Chris@example.com</code> can't be used with the service.
</p>
<p>
So, go ahead and play in the comments a bit.
</p>
]]>
    </content>
  </entry>
    
  
    
  
    
  
    
  <entry>
    <title>null program Turns Two Years Old</title>
    <link rel="alternate" type="text/html" href="https://nullprogram.com/blog/2009/09/01/"/>
    <id>urn:uuid:5c47675e-fe5c-3ae4-a5e9-c8252b729276</id>
    <updated>2009-09-01T00:00:00Z</updated>
    <category term="meta"/>
    <content type="html">
      <![CDATA[<!-- 1 September 2009 -->
<p>
This website/blog turns two years old today. That's right, the first
post was on September 1, 2007. This also happens to be the 100th post!
Woo! Which means I have nearly kept up with my original <a
href="/blog/2007/09/01/">one post per week planned average</a> (104
would put me on schedule).
</p>
<p>
The site has evolved a bit in that time. Two years ago I was using
vanilla blosxom (I've since hacked it up), no comments, no portrait
(portraits increase reader trust), simpler logo, no color, no RSS (it
was there, but I wasn't linking it), crappy index, no features but
this blog and the "projects" section, no Creative Commons license (but
I've always had the other simple copyleft statement), no lisp, and
only one permalink per post. Since I started this site I lived in
three different US states, had two different jobs, bought two
computers, bought a car, adopted a cat, learned several programming
languages, graduated with a bachelor's degree, had major surgery, and
got married.
</p>
<p>
I've tried to make all my posts more than a trivial "hey, check this
link out", and instead have some real content for each one. Thanks to
this, if you concatenate all the posts together it's long enough to be
a short book (about 170 pages). And, this blog is
100% <a href="http://en.wikipedia.org/wiki/Free_Culture_movement">
Free Culture</a>. All text and images are public domain or under a
Free license (and none of that non-commercial-only crap). So I — or
anyone — could easily publish it as a book. (Ha! As if anyone would
buy it!) And I <i>do</i> maintain another completely separate blog,
with a (currently) higher post frequency, under a pseudonym (so I
don't get myself into trouble), which is why I won't tell you what it
is. :-)
</p>
<p>
I'm really happy I kept kept this "log" of my activities. I've had
some real misconceptions about my previous self, which the log has
cleared up. I often think I came up with ideas or had viewpoints much
more recently than I really did ("Oh, learning Scheme really
<i>was</i> that long ago."). I wish it went back further, because, for
example, I really am not sure at which point I became an atheist
(early 2003?) or a left libertarian (summer 2003?). I tend to think of
my previous self as more stupid than I really was, which gives me this
false impression of intellectual progress, when really I am as dumb as
I ever was! I know one one thing for sure, my writing hasn't really
improved!
</p>
<p>
So, thanks for reading! If you don't already have a blog, start one
today. Keep up with it, and at two years I'm sure you'll be really
glad you have it.
</p>
<p>
Here's to another two years!
</p>
]]>
    </content>
  </entry>
    
  
    
  
    
  
    
  
    
  
    
  
    
  <entry>
    <title>Converted to HTML 5</title>
    <link rel="alternate" type="text/html" href="https://nullprogram.com/blog/2009/06/30/"/>
    <id>urn:uuid:d3f1f505-10db-318e-8b7a-eda3894e1eaf</id>
    <updated>2009-06-30T00:00:00Z</updated>
    <category term="meta"/>
    <content type="html">
      <![CDATA[<!-- 30 June 2009 -->
<p>
I converted this website to HTML 5 from its original XHTML 1.0
Transitional. Because I was already valid, it was actually pretty
easy. Well, I first converted it to XHTML 1.0 Strict by shifting some
things into CSS that should have been that way in the first place
(results of laziness). Then when that validated I just changed the
DOCTYPE to HTML 5, added a new<code> meta</code> tag, checked
<i>that</i> validation and that was it. Really simple.
</p>
<p>
One of the main reasons was so that I could use the new
<code>video</code> tag. From now on any posts with videos will display
them as in-line videos (Ogg Vorbis), provided you are using a browser
with HTML 5 support. In fact, I already did it with two older posts:
<a href="/blog/2009/05/27">Knight's Tour</a> and the <a
href="/blog/2007/10/01">Mandelbrot set zoom videos</a>.
</p>
<p>
HTML 5 is still a moving target, so I <i>may</i> have to do some
keeping up over time. Probably not.
</p>
<p>
Video is finally a first class web citizen and it is quite exciting.
</p>
]]>
    </content>
  </entry>
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  <entry>
    <title>I Finally Have Comments</title>
    <link rel="alternate" type="text/html" href="https://nullprogram.com/blog/2009/05/12/"/>
    <id>urn:uuid:19b5b979-433a-3529-2a61-d25abd07a5b9</id>
    <updated>2009-05-12T00:00:00Z</updated>
    <category term="meta"/><category term="netsec"/>
    <content type="html">
      <![CDATA[<!-- 12 May 2009 -->
<p class="abstract">
Update: This post is referring to my old web hosting situation. I'm
now using external comment hosting because my blog is now statically
hosted.
</p>
<p>
I finally have a comment system, thanks to <a
href="http://www.nukekiller.net/pollxn/">pollxn</a>, a <a
href="http://www.blosxom.com/">blosxom</a> comment system that
actually works. There is a link to it, indicating the number of
comments, in the bottom of each post. Try it out and say hello.
</p>
<p>
Unfortunately, pollxn doesn't have any sort of anti-spam or <a
href="http://en.wikipedia.org/wiki/Captcha"> CAPTCHA</a> system. If
you look around the Interwebs where other people are using pollxn, you
will see everyone has their own little CAPTCHA thing. Well, I am not
different. I hacked together my own to keep away automated spammers.
</p>
<p>
It selects words from the dictionary (of 40,000 words in this case)
and encrypts them with Blowfish in CBC mode, with a unique IV each
time. This is to passed to the user, who passes it to an image
generator which decrypts the word and uses GD in Perl to render it,
apply some transforms, and drop a line randomly over it. The user
submits the guess of the image along with the encrypted version
(hidden field), which is decrypted and compared on the other end. The
same encrypted ID cannot be used twice, but thanks to the IV the same
word <i>can</i> be used twice.
</p>
<p>
Here are some samples. If you hit refresh, they will render
differently. (<i>Update: not any more. These are just static examples
now.</i>)
</p>
<p>
<img src="/img/captcha/a.png" alt="CAPTCHA sample: ormolus"/>
<img src="/img/captcha/b.png" alt="CAPTCHA sample: morons" />
<img src="/img/captcha/c.png" alt="CAPTCHA sample: softer" />
<img src="/img/captcha/d.png" alt="CAPTCHA sample: zanucks" />
<img src="/img/captcha/e.png" alt="CAPTCHA sample: grumble" />
<img src="/img/captcha/f.png" alt="CAPTCHA sample: nozzle" />
</p>
<p>
It's not a great CAPTCHA, but it should be good enough for the low
volume of traffic I see here. As I inevitably collect small amounts of
spam (by spammers manually passing the CAPTCHA), I will gradually
create the needed tools to combat it. I can also easily update the
CAPTCHA image algorithm without disrupting the functioning of the
website.
</p>
<p>
I'm sure I will be making improvements to the comment system over time
as well. I should make it obfuscate e-mail addresses, for one. Maybe
add a preview. And better blosxom integration.
</p>
<p>
So say hello below! I am excited to finally have a <i>real</i> blog.
</p>
]]>
    </content>
  </entry>
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  <entry>
    <title>null program is Alive</title>
    <link rel="alternate" type="text/html" href="https://nullprogram.com/blog/2007/09/01/"/>
    <id>urn:uuid:01475da9-58d6-36ac-e652-ce88c48b6b02</id>
    <updated>2007-09-01T00:00:00Z</updated>
    <category term="meta"/>
    <content type="html">
      <![CDATA[<p>Welcome to <strong>null program</strong>. This is my new home as my <a href="http://www.cse.psu.edu/~wellons">student
location</a> will no longer exist in a
few months. Here is where I will share my projects and ideas, even if
no one is looking, reading, or caring.</p>

<p>The name for this website comes from a phrase spoken in several places
in my favorite book, <em>The Moon is a Harsh Mistress</em>. If you have not
read this book, you are missing out. I recommend you go to the nearest
library immediately and read it. Amazon lets you <a href="http://www.amazon.com/gp/reader/0312863551/ref=sib_dp_pt/103-6664886-7819837#reader-link">read the first
chapter online</a> if you want to get a taste of it. When I started
reading it, I was hooked right away. Why is it a great book? Because
it is about an American Revolution style libertarian revolution on the
moon, and the hero character is a computer engineer. What book can get
better than that?</p>

<p>I would like to post something interesting here about once a week or
so. I am taking classes right now, so getting ideas should be
relatively easy. The first few posts will probably be repeating things
I have already published at my old student location. This will include
little intros to my old projects and a bunch of code snippets.</p>

<p>Also, separate from this blog thing are my projects, such as the PNG
Archiver and binitools. <del>These have a permanent home located under
projects/</del>. (<em>No longer here, after changing web hosts.</em>)</p>

<p>I am a big <a href="http://en.wikipedia.org/wiki/Free_software">free software</a> fan and you will probably see the
<a href="http://www.gnu.org">GNU project</a> being mentioned a lot around here. I also use
<a href="http://www.gnu.org/software/emacs/">Emacs</a> for just about everything I can. Here is more advice:
learn to use Emacs. You will become much more productive. After using
Emacs for awhile, you will begin loathing word processors and mice
(the computer kind). More on this later.</p>

]]>
    </content>
  </entry>
    
  

</feed>
