Posts in "geek"

Just Get Home Already

While waiting for Jen to return from a conference, I thought about calling her to get her estimated time of arrival, or her ETA. I realized she might be might be pretty far away still and thought I better ask for an estimate of the accuracy of the estimate, or meta-estimate: her META. Hey, neat! META can be a recursive acronym for “meta-ETA”, so it also references the nature of the acronym itself, sort of making META a meta-acronym, which truly makes it both meta and META.

In Defense Of The Model M

There are few joys in life like using something that is the perfect expression of its intent. Each trade has its representative tools, and their common trait is quality, even if it’s not obvious to the casual observer, and often counterintuitive. The best tools in a category are almost always the least flashy, and rarely the ones a new practitioner would choose.

The Model M keyboard is like that: it’s loud, ugly, heavy, and utterly lacking modern niceties like buttons to change your sound volume or check your email. And yet, it has that transcendent feeling that’s hard to explain, that sense of rightness where you realize that you’re using the best that’s ever been made, that every change since then has been superfluous and cosmetic. With time, the loud clacking becomes the background music of your work, the harmony that tells you that your thoughts have become words. Its beige boxiness yields to elegant simplicity and the realization that true beauty is born of function, not appearance. The sheer weight of the thing turns to solidity and the confidence that it will stay where you put it. The dearth of features becomes the singleminded dedication to the parts that really matter and a proud disregard of unneeded distractions.

A tool attains its peak when a craftsman forgets that he’s using it because it has become an extension of himself. Thus the humble Model M has become the iconic favorite of hackers everywhere, an ode to the engineers who grasped for excellence and acheived it.

Fun With Software Licenses

Did you know that you’re probably not allowed to make backups of your computer? It’s true, if you believe in the legal fiction known as “End User License Agreements” (or EULAs), which are those annoyingly long contracts where you have to click “I Agree” before you’re allowed to install some program or another.

For example, here’s a snippet of the Adobe Integrated Runtime (AIR) End User License Agreement:

2.3 Backup Copy. You may make one backup copy of the Software, provided your backup copy is not installed or used on any computer.

Nice, huh? If you install this software, its EULA forbids you from making more than one backup copy. This is a deal-breaker for business which keep multiple backup archives from days, weeks, and months past. According to this agreement, you could hypothetically alter your corporate storage system to ignore each of the files that would be installed, but realistically no one would ever even attempt this.

This is just one more reason to be grateful that EULAs are almost universally believed to be legally unenforcable. However, unless you’re willing to tell a jury that you don’t think you’re bound by such an agreement, remember that every piece of software with a similar license is a potential time bomb. Theoretically, you could be sued just for having it, even if you probably wouldn’t be found liable.

Fans of commercial software often talk about the “impracticality” of Free or Open Source Software, but the alternatives are starting to look a lot worse.

Buffer Overrun In Antitrust

Skip this unless you’re really, really geeky.

Still with us? OK. In the movie “Antitrust”, there’s a screenshot of some code that has a possible Denial Of Service vulnerability:

/* are we doing a GET or just a HEAD */
boolean doingGet;
/* beginning of file name */
int index;
if (buf[0] == (byte)'G' &&
    buf[1] == (byte)'E' &&
    buf[2] == (byte)'T' &&
    buf[3] == (byte)' ') {
    doingGet = true;
    index = 4;
} else if (buf[0] == (byte)'H' &&
           buf[1] == (byte)'E' &&
           buf[2] == (byte)'A' &&
           buf[3] == (byte)'D' &&
           buf[4] == (byte)' ') {
    doingGet = false;
    index = 5;
} else {
    /* we don't support this method */
    ps.print("HTTP/1.0 " + HTTP_BAD_METHOD +
               " unsupported method type: ");
    ps.write(buf, 0, 5);
    ps.write(EOL);
    ps.flush();
    s.close();
    return;
}

Because I can’t resist such things, I paused the movie to read over the code. Now, I’m assuming this is Java instead of C++ because “boolean” wasn’t spelled “bool”, although I’m not sure why they’d be using Java for performance critical code. Anyway. See the ps.write(buf,0,5); line near the end? Well, “buf” is presumably the string that the client sent to the server. If the client is broken (or malicious) enough to misspell “GET” and “HEAD”, then the server politely tries to tell the client what it did wrong by sending “buf”’s value back.

Which brings us to the hack. If “buf” is less than five characters long, then that “ps.write” line will attempt to read past the end of “buf”. If the calling function doesn’t handle index error exceptions, boom! The service crashes: Denial Of Service. Note that this is still better than the C++ equivalent, which would write the contents of memory immediately following the end of “buf” back to the client.

No, I’m not exactly good at sitting back and watching movies.

Don't Bump That Flash Drive

From the manual of an Asus Eee PC:

The solid-state disk drive’s head retracts when the power is turned OFF to prevent scratching of the solid-state disk drive surface during transport.

I think someone got a little zealous with the find-and-replace.

How Not To Save A Game

I was about halfway through a game called “Final Fantasy XII: Revenant Wings” on my Nintendo DS. I was having a great time and loving it until a stupid bug wiped out all the work I’d put in and made me start over.

When I was in the middle of a particularly involved battle, the red “low battery” warning light came on, so as soon as I finished I tried to save my game. Big mistake. The DS used up its remaining power during that instant and turned itself off. When I plugged it into the charger and turned it back on, I got a message saying that my game file was corrupt and had been deleted.

OK, in retrospect, I should have plugged my DS into the charger before I tried to save my game. Still, it should be impossible to destroy your old information by writing a new version of it. That’s just good design. Unfortunately, FFXII doesn’t have a good design. See, the problem is that FFXII saves its game by writing over the pre-existing save file. Since the power died during that write, the results were half old game and half new game. Hence corrupt. Hence deleted. Here’s how a competent programmer would handle the same situation:

  1. Create a new save file and write the information to it.
  2. Delete the old file.

See the difference? At no point do the two files get mingled together, and the old file stays valid and ready to use until the new one is completely written. In the absolute worst case of a power failure during the saving process, you’d lose the new information but the old data would still be intact and safe.

I don’t know whether the buggy code was written by Square Enix, or if they were using Nintendo’s built-in game saving method. Regardless, it’s dumb and should be fixed ASAP for all new games.

Yam No More

Back in my Amiga-using days, I had an email program called YAM. It was excellent and ubiquitous; almost everyone used it. It had three unique features:

  • You could configure it to embed small bits of personal information in outgoing emails, such as your birthday.
  • When it saw these bits in email that other people sent to you, it could add the information to your address book.
  • It had an option to automatically send a “happy birthday” email to everyone in your address book on their birthday.

I was active on a lot of mailing lists, so my address book was pretty full with people I’d hardly met. I sent them happy birthday emails each year, and on my birthday, it was fun to get flooded with a few hundred little messages from well-wishers I didn’t know except maybe from some obscure discussion group.

I had the sad realization a few days ago that for the first time ever since I started using YAM, I didn’t receive a single email from it this year. Not one of my old friends still does this. While it’s not very big in the scheme of this, it still marks the sad end to a happy era.

Becoming Unrooted

So, I forgot my root password. For non-technical types, that’s pretty much the key to the kingdom when you need to get full access to a computer, or install new software, or to make backups, or to fix something in an emergency. I use this little program called “sudo” all the time that lets you do most of the same things except with your own password. I guess it’d been so long since I’d actually needed that root password that it just slipped my mind. Still, I felt pretty dumb and resigned myself to coming up with a new one and resetting it on all the computers I use.

So, this morning something came up where I really needed that password, and without thinking I picked up a keyboard and mashed it out. It worked. “Oh joy,” I though. “I’ll just do it again and pay attention to what I’m typing.” Except that try as I might, I just can’t type that password if I’m consciously thinking about it.

This has not improved my outlook on an upcoming birthday in the slightest.

baby.lisp

In our household, a baby just ain’t a baby without an appropriately geeky birth announcement. And since Nick is mostly functional — I mean, he can’t exactly type yet — this one is in Lisp. Share and enjoy!

; This program forks().  That should be plenty for a few years' entertainment
; Copyright (C) 2007 Kirk & Jennifer Strauser

; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.

; However, the output of this particular instance shall remain
; exclusively licensed to the authors for a period of up to eighteen
; years.

; $Id: baby.lisp 4 2007-09-05 23:18:12Z kirk $


(require :sb-posix)

(defvar *birthtime* (encode-universal-time 0 20 1 1 9 2007))

(defvar *age* (- (get-universal-time) *birthtime*))

(defun hello ()
  (format t "Hello, world!  My name is Nicholas Arthur Strauser and this is ~
my ~:r day!~%" (ceiling (/ *age* 86400))))

(defun labor ()
  (cond
   ((zerop (sb-posix:fork)) (format t "Ouch!~%"))
   (t (hello))))

(defun wait ()
  (cond
   ((< *age* 0)
    (sleep (- *age*))
    (setf *age* 0)
    (labor))
   (t (hello))))

(wait)