The Boston Diaries

The ongoing saga of a programmer who doesn't live in Boston, nor does he even like Boston, but yet named his weblog/journal “The Boston Diaries.”

Go figure.

Monday, February 01, 2010

Yet another Bill Watterson interview found!

Ah, the life of a newspaper cartoonist—how I miss the groupies, drugs and trashed hotel rooms!

But since my “rock star” days, the public attention has faded a lot. In Pop Culture Time, the 1990s were eons ago. There are occasional flare-ups of weirdness, but mostly I just go about my quiet life and do my best to ignore the rest. I'm proud of the strip, enormously grateful for its success, and truly flattered that people still read it, but I wrote “Calvin and Hobbes” in my 30s, and I'm many miles from there.

Via Hacker News, Bill Watterson, creator of beloved 'Calvin and Hobbes' comic strip looks back with no regrets | Living - -

It's not the best Bill Watterson interview (a much better interview was done by Andrews McMeel Publishing) but that answer is just great.

The reason for even linking to this is that any interview with Bill Watterson is a very rare event. Heck, even pictures of the artist are very rare and so far, I think this is the only picture I've seen of him:

[Reminds me of Calvin's dad, or maybe his uncle Max]

Quite the recluse, that Mr. Watterson.

He's also famous of not allowing any Calvin and Hobbes merchandising, although it does appear he relunctantly gave his endorsement for a new product coming out in July:


Wednesday, February 03, 2010

Perhaps an 80M script isn't that excessive …

Around three months ago, I found a bug in Lua (and yes, it's silly to run an 80M script, but then, I tend to do silly things with programs). I reported the error to the Lua mailing list, and a few days later it was posted as a known bug with a one line patch to fix it.

And yes, I just got around to retesting Lua (with a version that has every patch applied, including the patch for the bug I found) with my 80M script:

[spc]lucy:/tmp/lua>time lua -i show.lua
Lua 5.1.4  Copyright (C) 1994-2008, PUC-Rio
> dofile("default.lua")
> os.exit()

real    0m10.964s
user    0m5.880s
sys     0m0.376s

Much better.

Lua just in time

Playing around with Lua is fun, but I've been hearing some good things about LuaJIT, a “just in time” compiler for Lua for the x86 platform (written by a single guy, no less!). Even more amazing, it's literally a drop in replacement for Lua (both the command line interpreter and library).

Okay, I'm willing to give this a try. I download, compile and install it. I then decide to test it using jumble program I wrote in Lua. All I need to do is change one line:


to read:


and rerun the program.

Lua version of Jumble program
versiontime in seconds
pure Lua 7.74
pure LuaJIT3.57
Lua + C 2.06
LuaJIT + C 1.70

LuaJIT easily trounces the Lua interpreter without any code changes (other than specifying a different “interpreter”). The versions with C use a C function to sort the letters in the word and while LuaJIT was faster than the Lua + C version, the very fact that I didn't have to modify any code is fantastic! LuaJIT used the very same C code as the Lua version—no changes or recompilations required!

Very neat!

I just relinked my Lua daemon against LuaJIT, just to test it out, and yes, it worked without any changes. I could even reload the scripts on the fly. And incredibly, it's only about 50% bigger than Lua itself.

LuaJIT is one sweet piece of technology.

I can't remember the last time I used a printer …

I hate printers.

All I wanted to do was print out a 13 page file using both sides of the paper. It was easy enough to select the odd pages, then the even pages in the printer software. The hard part? Knowing which way to orientate the papers for printing on the second side.

It took me four attempts to get it correct.


So much for saving paper …

Saturday, February 06, 2010

Thinking outside the dusty box

My computer has a rather odd cutout in the front that tends to accumulate dust:

[No, it doesn't glow; I'm just lighting it from behind.]

I've noticed recently that it's accumulated a metric buttload of dust (the shot above is after I've removed quite a bit of it, as shown below). Even Mark remarked how dusty it was in there.

So, the problem: how to go about dusting the thing. It was a thick blanket of dust, and I headed into the garage of Chez Boca thinking I might find a vacuum with a nozzle attachment that would fit in there when I came across the perfect solution:

[Not just for breakfast anymore]

The Lint Roller!

It's really just a very wide roll of masking tape with the sticky side out. The method is easy: just remove the outer sheet (it's about 6″×4″) and apply it to the dust.

[Forced evacuation of dust bunnies]

A few lint sheets later and the computer is now dust free.

Sunday, February 07, 2010

Heaven forbid he ever try to climb a tree (not like it's easy to climb palm trees … )

I'm beginning to think child safety is getting way out of hand. I was driving home from resolving a customer issue (nothing major—just needed to reset a port on a switch—thank you ever so much, Monopolistic Phone Company), driving down the street towards Chez Boca when I saw a kid, maybe four or five years old, wandering about, on foot, close to home (easily within 50′ of the front door), wearing a bicycle helmet! There was no sign of any type of pedal-powered vehicle in the vicinity, although his mother was nearby, sitting on the front lawn watching out for the little kid.

He was wearing a bicycle helmet while walking!

Around his age, I was flying headfirst into ditches on my bicycle sans helmet and the only lasting affect is an inability to spell sertain words correctly. Well, that, and a tendency to say “that” instead of “who.”

He was wearing a bicycle helmet while walking, people!

Then again, I should be amazed he was let outside at all …


Sean Conner <>
Re: Password updated
Tue, 5 Jan 2010 11:24:10 -0500 (EST)

On Tue, 5 Jan 2010, Sean Conner wrote:

What's the cookie2 header for?

I'm so glad you asked. This is almost so good it may cause you to blog about it (actually I figured by the time we were done discussing the insanity of cookies you may have had an insightful blog post anyhow).

I guess after the third cookie spec they figured they kinda sucked at this so they built in an escape. So after much re-re-re-reading of the RFC I think what happens is if you have received a cookie with a $Version that you don't understand you are supposed to just send back a Set-Cookie2: header with $Version="version_this_thing_understands"

It's for future expandability so when we have 10 cookies specs clients and servers will “just work” (at this point I think we both know that statement is about as truthful as “the check is in the mail.”).

Well Mark (and yes, I know, it's been a month), the cookie specs are a paragon of clarity compared to the laughable mess that is syslog protocol specification. Had I been aware of the “informational nature” of RFC-3164 I might not have even started my own homebrew syslogd replacement (network stuff in C, high level logic in Lua).

How loose is the spec?

A program that wishes to use syslog() may select a “facility” the message will be logged under—think of “facility” as a subsystem, like “mail” or “cron” (under Unix, cron runs scheduled tasks on a periodic nature) or “auth” (authorization, or login credentials). Also, each message has a priority (kind of), one of “debug”, “info”, “notice”, “warn”, “err”, “crit” (for critical errors), “alert” (even more critical errors) and “emerg” (basically, the machine is on fire, abandon all hope, etc.). The program using syslog() can also tag each message, usually with its name, and the message itself has no real structure, originally being meant for human consumption.

Now, the syslog protocol, which is used to send the messages to a program that handles these messages, usually named syslogd under Unix, is a text based protocol, and a full RFC-3164 message would look something like:

<87>Feb 07 04:30:00 brevard crond: (root) CMD (run-parts /etc/cron.hourly)

You have the facility and priority (as a single number) in angle brackets, immediately followed by the timestamp, a space and then the name of the machine sending the message, a space and the tag (usually the name of the program on the machine sending the message), a colon, then the message.

And technically, every field is optional! Which makes parsing this a technical challenge. Not only that, but since there never really was a spec, it's easy to find ambiguous messages, such as:

<14>Jan 14 05:53:37 gconfd (spc-25469): Received signal 15, shutting down cleanly

which (per the spec) was sent from the program “(spc-25469)” on machine “gconfd”. Funny thing is, I have no machine called “gconfd” but there does exist a program called gconfd that runs on my machine, running as me, with a process ID of 25496 (fancy that).

I don't even want to talk about /Applications/Windows Media Player/Windows Media

It gets even worse. RFC-3164 makes a point in saying that the following is a legal syslog message that has to be processed:

Use the BFG!

Just writing the code to parse this mess took the majority of time, as I kept coming across syslog messages that really weren't.

To work my way out of this mess, if I don't find a proper facility/priority field, I log the raw message (using facility “user” and level “notice”, which is what RFC 3164 says to use in the absence of such information). If there's no timestamp, okay, but if there is one but it's malformed, I log the raw message. I then check for an IP or IPv6 address, as I feel that's really the only sane value to use, then everything else up to a ':' is accepted as the tag value (more or less).

Is it perfect?


But so far, it covers everything I've personally encountered. It will misparse (which is a testcase I pulled from rsyslogd), but not crash, on seeing:

<130> [ERROR] 2008-09-23 11-40-22 PST iapp_socket_task.c 399: iappSocketTask: iappRecvPkt returned error

Garbage in, garbage out (also, stuff like this can be checked in the Lua code, as the raw message is available in addition to the parsed message).

Cookies? Insane? Not really. Not when compared to the syslog protocol.

More than you care to know about syslog

So I've been learning more than I ever wanted to about the syslog protocol. There's the non-spec that is RFC-3164 that is optimistic in terms of the protocol. Then there's the cleaned-up spec that no one is using that is RFC-5424 (which is quite nice, if a bit over-engineered).

RFC-3164 documents the use of UDP as the transport protocol for the syslog protocol, reading that RFC one gets the impression that one should never actually use UDP as the transport mechanism, least some cracker intercept or change the messages, or worse yet—you lose some packets and get nailed in an Sarbanes—Oxley audit (or even worse still—an ISO-9000 audit—the horror! The horror!).

Well, you could try running the syslog protocol over TCP, but even that isn't good enough for some people, claiming that you can still lose logging information under certain circumstances. No, for reliability you need to add a layer of framing over TCP and wrap the syslog protocol in XML and call it a day.

So far, the only syslog program I've found that even pays RFC-3195 lip service is rsyslogd, and even then, it's receive only and uses its own framing layer over TCP for sending.

I personally haven't seen an issue with using UDP for the syslog protocol. Not only do I relay syslog messages to a centralized server (my desktop box at Chez Boca, so I can watch the stuff in real time) but copies are kept locally (just in case). Also, there have been times when a TCP version (yes, even if I was using RFC 3195 or the lighter RELP) would have failed (at one point, our upstream provider upgraded a firewall that filtered out TCP traffic routed asymetrically and guess what? Our traffic was routed asymetrically; UDP traffic was unaffected and thus in that case, we were able to isolate the issue faster). Even the design of SNMP centered around UDP simply because it was “fire and forget” and thus on a congested network, there was a greater chance of UDP traffic of making it out and accepted than TCP traffic (which requires an acknowledgment that might never make it back).

But in looking over these, I'm struck that a reliable syslog protocol doesn't use SCTP, which has the reliability, ordering and (most importantly, congestion control) of TCP with the message-based semantics of UDP. Heck, for “reliability” SCTP has one feature that neither TCP nor UDP have: either peer can change the IP address used for the session.

For now, I'll just stick with UDP.

Tuesday, February 09, 2010

Syslogintr—a syslogd replacement in C and Lua

So, why did I decide to write my own syslogd? Well, it was started as something to do while at Bunny's mom's house. I was curious as to the actual protocol used by syslogd because it's always bugged me that the files written by syslogd bear no information about the facility or priority a message originally had. Sure, you can filter by the facility and priority, but the resulting files lose that information.

It was after reading RFC-3164 that I realized it might be possible to filter on more than just the facility and priority. Have Lua handle the logic of log analyzation and I had what I thought was a fun little project.

Heh. Little did I know.

Anyway, it's been in use for a little over three months (and 140 commits to the source repository) and I must say, I'm finding it very useful. Sure, I could have written a Lua script to parse the log files that the traditional syslogd writes, but I'm just cutting out the middleman filesystem.

So the C code accepts, parses and hands a well-structured block of information to the Lua code, and it's the Lua code where all the features are implemented.

The information to Lua is passed in a table (which is Lua for an associative array, or hash table) with the following fields:

Formatted syslog message as passed to Lua
versionnumberThis is the version of the syslog protocol, of which there are two—the documented version 1 which I haven't seen in the wild yet, and the conventional version which I've internally labelled as “version 0”. I currently only support version 0, so this field (as of this writing) is always 0.
_RAWstringThis is the actual raw message as received. It was intended as a debugging aid, but I keep it enabled as it is useful when you get the odd message.
remotebooleantrue if the message came in over the network, false if it was generated locally on the machine. I use this as a quick test.
hoststringThis is really the source of the message. For a remote syslog message, this will contain the IPv4 or IPv6 address. For messages generated locally, this will be the “local socket” (formerly known as “Unix sockets”) the message was written to (which on most systems is /dev/log).
relaystringUsually this will be the same as the host field, but when syslog messages are being relayed, this is the intermediate system that relayed the message on. If system A generated a message to B, and B relayed it to C, then the host field will contain “A”, but the relay field will contain “B”. If, however, it goes A → B → C → D, then host will contain “A” and relay will have “C” (in other words—the relay field will only contain the last relay machine).
portnumberThe UDP port number the syslog message was sent from. If the message was sent locally, this will be -1.
timestampnumberThis is the timestamp the message as it was received on the accepting host. This value is suitable for use in the Lua functions and os.difftime().
logtimestampnumberThis is the timestamp as found in the syslog message (if there was one). Otherwise, it will be the same as timestamp.
programstringThis is really the tag portion, but since it's mostly the name of the program that generated the syslog message, that's what I called this field. If it wasn't given, the value of this field will be “”' (an empty string, not nil).
pidnumberThe process ID of the program that sent the message. Most Unix syslogd implementations have this as part of the tag, and if found, is set here. Otherwise, it will be 0.
facilitystringThe facility, which will be one of the following:
  • kernel
  • user
  • mail
  • daemon
  • auth1
  • syslog
  • lpr
  • news
  • uucp
  • cron1
  • auth2 (also known as “authpriv”)
  • ftp
  • ntp
  • auth3
  • auth4
  • cron2
  • local0 through local7
levelstringThis is the priority of the message, but the term “priority” never made much sense, so I call it “level.” This will be one of eight values:
  • emerg
  • alert
  • crit
  • err
  • warn
  • notice
  • info
  • debug
msgstringThe actual message, or basically, whatever is left after parsing everything else. This is pretty much a free-format string.

This table is passed to a function called “log()” to handle however. On my development system, this function is simply:

function log(msg)

writelog() just logs the message to a single huge logfile (that records the host, program, facility, level and msg fields). It's the sshd() function that's interesting:

if blocked == nil then
  blocked = {}

function sshd(msg)
  if msg.remote   == true    then return end
  if msg.program  ~= "sshd"  then return end
  if msg.facility ~= "auth2" then return end
  if msg.level    ~= "info"  then return end

  local ip = string.match(msg.msg,"^Failed password for .* from ::ffff:([%d%.]+) .*");
  if ip == nil then return end

  I_log("debug","Found IP:" .. ip)

  if blocked[ip] == nil then
    blocked[ip] = 1
    blocked[ip] = blocked[ip] + 1

  if blocked[ip] == 5 then
    local cmd = "iptables --table filter --append INPUT --source " .. ip .. " --proto tcp --dport 22 --jump REJECT"
    I_log("debug","Command to block: " .. cmd)    
    I_log("info","Blocked " .. ip .. " from SSH")
    table.insert(blocked,{ ip = ip , when = msg.timestamp} )

This checks for local messages from sshd and if it finds five (or more) consecutive failed attempts, adds the IP address of the offending party to the firewall, and logs the attempt (via I_log()). Nothing that a lot of intrusion scripts don't already do, but this is in the syslog daemon, not another process reading this second hand through a file (and without the issues that come up with log rotation).

Now, in order to keep the firewall from filling up, I added yet another feature—the ability to periodically run a Lua function. So, elsewhere in the script I have:


function alarm_handler()
  I_log("debug","Alarm clock");
  if #blocked == 0 then
    I_log("debug","Alarm clock---snooze button!")

  local now = os.time()

  I_log("debug",string.format("About to remove blocks (%d left)",#blocked))

  while #blocked > 0 do
    if now - blocked[1].when < 3600 then return end
    local ip = blocked[1].ip
    I_log("info","Removing IP block: " .. ip)      	
    blocked[ip] = nil
    os.execute("iptables --table filter -D INPUT 1")

alarm() informs the C code to call the function alarm_handler() every 60 minutes (if you give alarm() a numeric value, it takes that as a number of seconds between calling the function, if a string, it expects a numeric value followed immediately by “m” for minutes, “h” for hours (so I could have specified “1h” in this case) and “d” for days). The function alarm_handler() then removes the blocks one at a time (once per hour) which is long enough for the scanner to move on.

Now, you may have noticed this bit of odd code:

if blocked == nil then
  blocked = {}

One feature of the C code is that if it receives a SIGUSR1, the Lua script will be reloaded. This is to ensure that if there is any IP blocks defined, I don't lose any when the script is reloaded (and yes, that is a handy feature—change the Lua code a bit, and have the daemon reload the script without having to restart the entire daemon).

Along those lines, if the C code receives a SIGHUP, calls the Lua function reload_signal(), which allows the script the ability to close and reopen any logfiles it might be using (thus being compatible with the current syslogd behavior) which is useful for rotating the logs and what not.

I'm also running this on my own server (, which runs this blog) and also one of our monitoring servers at The Company (this one not only runs Nagios, Cacti and snmptrapd, but all our routers send their syslog information to this server). The Lua code I have running on the monitoring server not only keeps logging in the same files as the old syslogd (in the same format as well), but also this little bit of code:

function check_ospf(msg)
  if msg.facility ~= 'local1' then

  if string.match(msg.msg,".*(OSPF%-5%-ADJCHG.*Neighbor Down).*") then
  elseif string.match(msg.msg,".*(OSPF%-5%-ADJCHG.*LOADING to FULL).*") then

If the routing on our network changes, I get email notification of the event. I also have some code that processes the logs from Postfix. Postfix generates “thin entries,” five entries per email (from various subsystems) when what I really want logged are “fat entries” (which summarize the status of the email in one log line). So, I wrote some code to catch all five lines per email, and then just log a one line summary, thus changing a bunch of “thin entries” to one “fat entry” (what I really want to do is send all mail related logs on all our servers to one central location, so we no longer have to check two or three servers everytime one of our customers complains about email being “too slow” but that's for another show entry).

The Lua code on my personal server also does the Postfix “thin-to-fat” conversion, but it also logs the webserver status every hour (just because I can).

And if you're wondering why I've blathered on and on about a piece of code I've yet to release, it's because I've yet to write any documentation on the darned thing, and I figure this would be a decent first pass at some documentation. And maybe to gauge interest in the project.

Wednesday, February 10, 2010

Notes on logging

This is interesting: Facebook wrote their own logging system instead of using syslog. Their system only has two pieces of informtion—a catagory and the message. No facilities, no priorities or levels. I think in Facebook's case, they log everything so there's no need for individual priorities or levels (the argument here is: you're going to log everything eventually anyway, so simplify the process).

Another note: when your configuration file is too complex (or in other words—an ad-hoc declarative language) perhaps it's time to give up and just use a scripting language for configuration (I skipped straight to using a scripting language for configuration/logic).

More notes on logging

I mentioned yesterday about logging all mail related logs to a central server. While we don't have a complicated email setup (unlike, say, Negiyo), we still have several email severs and we get enough tickets about slow or lost email that it's a pain having to slog through one or two servers piecing everything together. What I would like is, given a Message-ID (which is (supposed to be) a globally unique identifier for an email) or an email address, to make a query in one location and get something like:

message-id = <>
from =
to   =
[]   []       Feb 10 22:46:56
[]       [] Feb 10 22:46:57
[]         [] Feb 10 22:47:02
[] []  Feb 10 22:47:06
[]  mbox of sean               Feb 10 22:47:06

As an example, you see the Message-ID, who sent the email, who received it, and the five other lines can be read as: machine X sent email to machine Y at such-n-such a time,” with the last one showing local delivery of the email to a mailbox.

Anyway, that's what I would like to build. And I can almost do it. Sendmail (which at The Company we use on our legacy systems), Postfix (which we use for new servers) and Exim (which we use on one server because it has a feature that's needed by a program that runs on that one server) all log a bunch of messages as email works through their respective systems. Each one uses an internal unique ID, but they at least log the Message-ID at some point, so I can map the respective MTAs internal IDs to a globally unique ID.

The odd-man out though, is our spam firewall, which is used by a significant portion of our customers. But, given that our spam firewall is OpenSource™ I suppose I can modify the source code to emit a Message-ID, but the problem there is if (or when) we upgrade—I would have to patch the code again (or, convince the Powers That Be to accept the patch).

I would also like to convert as many software packages to log via syslog, and while most, like PostgreSQL and even Apache, can be configured as such, there are a few holdouts (I'm looking at you, MySQL) that can't.

Wednesday, February 17, 2010

Dragons and Thunderstorms

Four months ago I attended a Drupal users group and I was underwhelmed since the group was mainly web developers, not programmers. So of course I found myself at a Ruby users group (so close that Wlofie and I walked there).

I went not because I'm terribly interested in Ruby (although getting a feel for the language certainly won't hurt) but because an old friend from college, Steve Smith had organized the meeting and I thought it might be nice to drop in and say hello.

It turned out that this group was more aligned with my interests than the Drupal users group. The first presentation was on distributed Ruby, which had a unique feature—if the local side could not marshall an object to send to the remote side, it basically signaled the other side to make a remote call back to do the actual processing, so neither side could really claim to be the client nor the server—both sides could act the role. It's a bit baroque for my tastes, but still, an interesting solution to a problem with remote procedure calls.

The second presentation wasn't a presentation as it was a discussion on design patterns in Ruby, which lead to a digression through the source code for Rails 3.0 and a few coding techniques that several of the more knowledgeable Ruby programmers in the room didn't realize were possible in Ruby (and a whole new way to write ravioli code—wow).

And oddly enough, they were interested in some of the projects I've done in Lua. So it's definitely a users group I can see going to again.

Friday, February 19, 2010

Glutton for punishment

Four months ago I attended a Drupal users group and I was underwhelmed, so I'm finding myself in a rather odd position—I'm giving a technical talk about Drupal at the 2010 Florida Drupal Camp tomorrow (Saturday—at <shudder> 10:00 am! Oh bother!) about the work I've done on “Project: DoogieHowser.”

I'm not sure what prompted me to volunteer for the presentation, other than misery loving company and a chance to rant about the sheer silliness of the project (or maybe just the guilty feeling from writing about that Drupal users group a few months back), but hey, I get a free trip to Orlando and other than the unholy earliness of the presentation, it shouldn't be that bad.

And besides, what could possibly go wrong with Smirk and me being out of town at the same time?

I should know better than that

“Oh, Sean,” said Smirk. “You know better than that!”

“I know, I know.”


Bunny warned me about asking what possibly could go wrong. Bunny and I encountered heavy traffic leaving the Boca Raton area, and I-4 was almost, but not quite, a parking lot at 7:30 pm.

But even that wasn't the issue. Nope. At 11:00 pm Smirk knocks on the hotel door. Apparently, one of our customers decided that tonight was the perfect night to rework their entire network and needed our help.

Head, meet desk.

Saturday, February 20, 2010

Notes from a hotel room from the middle of the night while listening to a heated discussion in Spanish

The Quality Inn room is very nice, but there were several men in a very heated discussion, outside as we were trying to sleep. Bunny called the front desk to complain, and was informed by the sole employee onsite at the time that the police were being called in to mediate the heated discussion.


An hour later, the very heated discussion was resolved, but that still left a bunch of people entering and leaving various rooms and making sure that their doors were closed shut.

I think things quieted down by 3:00 am, giving me a full three hours before the wakeup call.

Le sigh.

Just a quick note from a conference

Of course I'm blogging from the conference. Why do you ask?

My perspective on presentations

I managed to get through my presentation about “Project: DoogieHowser” although my presentation was a bit shorter than I expected it to be. But it appeared to go well with the audience.

[The presentation from my perspective]

Smirk has been recording all the sessions with the goal of putting up the videos at Drupal Maestro (where you'll be able to see my presentation, but not from my perspective).

And if that wasn't bad enough, I volunteered to do yet another presentation, this time about Git, since there was an open session and one of the suggestions for a topic was git. Since I use git, I figured I could do a quick rundown on how to use it.

A realization

While I was underwhelmed by the Drupal users group, I am not underwhelmed here at the 2010 Florida Drupal Camp.

But then again, I'm sitting through the Special Topics track, which have the more technical talks at the conference. Everybody has been very nice (obviously, they haven't read that post) and the catered lunch was quite good. I'm actually glad I came to this thing.

Now, to prepare for my git presentation

It is over

The git presentation was well received, as I briefly covered some basic git commands like git init, git add filenames… and git commit, along with a few different workflows one can do with git.

After that, a two-plus hour dinner at Macaroni Grill, dinner for 60.

Now, I crash.

Monday, February 22, 2010

Souvenir from a conference

I crashed hard, mainly because, I caught yet another cold (second this year so far—or perhaps a continuation of the first, it's hard to say). Snotty nose, tired, sneezing, the whole nine yards.

[Clockwise, starting at noon—tea cup, electric kettle, tea pot, loose leaf green tea, timer, tea spoon]

I really hate being sick.

Tuesday, February 23, 2010

Crawler Town

For my friends who are into Lego, I give you:

[Crawler Town]

Crawler Town (link via

Now, back to my regularly being sick

Wednesday, February 24, 2010



Hollywood is creatively bankrupt

Sad. Just so sad.

Obligatory Picture

[The future's so bright, I gotta wear shades]

Obligatory Contact Info

Obligatory Feeds

Obligatory Links

Obligatory Miscellaneous

You have my permission to link freely to any entry here. Go ahead, I won't bite. I promise.

The dates are the permanent links to that day's entries (or entry, if there is only one entry). The titles are the permanent links to that entry only. The format for the links are simple: Start with the base link for this site:, then add the date you are interested in, say 2000/08/01, so that would make the final URL:

You can also specify the entire month by leaving off the day portion. You can even select an arbitrary portion of time.

You may also note subtle shading of the links and that's intentional: the “closer” the link is (relative to the page) the “brighter” it appears. It's an experiment in using color shading to denote the distance a link is from here. If you don't notice it, don't worry; it's not all that important.

It is assumed that every brand name, slogan, corporate name, symbol, design element, et cetera mentioned in these pages is a protected and/or trademarked entity, the sole property of its owner(s), and acknowledgement of this status is implied.

Copyright © 1999-2024 by Sean Conner. All Rights Reserved.