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, January 01, 2007

Happy New Year!

Oh, it does appear that it is some sort of holiday today, something about it being a new year or some such silliness. Of course everyday is the start of a new year! For it was a year ago that it was the same date! Well, except for February 24th, which comes around once every four years, except on the other three years when it appears yearly.

Yes, there will be a test on this.

In other news, to show just how much of a geek I am, one of the things I did today was telnet to an actual IBM PCjr, complete with ISA network card and custom TCP/IP network stack.

How cool is that?

And no, this will not be on the test.

Maybe.

Tuesday, January 02, 2007

Nice thought, but I don't think it'll work as intended

I've been hearing about the $100 laptop for some time now, and the more I think about it, the more I think it's a bad idea, but I'm having a difficult time expressing why I think it's a bad idea.

I remember back to my own days in school. My first exposure to a computer was in 5th grade, but I didn't get any access until 7th. And for me, that lasted all of two classes before I was permanently banned from using the computer (and I was still two years away before getting my own computer).

Sure, some kids will use the computers as expected.

But I suspect more will use the computers in very unexpected ways.

Some of which could lead to trouble (some of the stuff I did in college, had I gotten caught, could have had me expelled—or worse).

But that's even assuming the laptops get to their intended audience. Perhaps I'm being too cynical, but given the fact that the United Nations “Oil for Food” program didn't exactly feed many Iraqis, or that two bit dictatorial leaders kill the educated or intentionally cripple education doesn't lead me to be very optimistic about this endevour (I'm also involved in an online discussion about this topic).


Computers in the classroom

I'm actually very dubious about computers in the classroom, and it's not because of any Luddism I might have (heck, I have trouble getting rid of computers). I'm dubious for multiple reasons, one for the over-reliance on technology aspect. And two, I think it's a huge waste of money.

Years ago, maybe ten or so, I was invited to a middle school in Palm Beach County (forgotten which one it's been so long) to give a talk about the Internet. So one week day I arrive at the middle school and get a tour of their computer lab.

Oh.

My.

God.

A huge room, with about 20 or so high end computers (wouldn't surprise me it was Apple Macintoshes—Apple was always big in the educational system) all networked together in this gorgeous lab. Large windows. No visible wires (all wiring ran in tasteful pipes running up from each desk).

It basically exceeded any computer lab in the Computer Science and Engineering Department at FAU.

And the first thing that ran through my mind was, how much money was wasted on this lab?

Twenty computers. Assume two students buddy up at each computer. Fourty students per class. At six classes per day (the number I had in middle school) that's 240 students that have access to these computers. Out of a school that probaby had close to 2,000 students (it was a huge two story middle school—way larger than the one I attended). That's 12% of the student population had access to this beautiful computer lab.

And I have no idea what they actually taught on the computers (when I attended high school, it was BASIC and Pascal programming, but I doubt that's done anymore). I thought that the money spent on the computer lab could have gone to better use. More teachers. Better text books.

Anything but expensive, fragile computers that the teachers probably couldn't operate.

(Oh, and the students I talked to about the Internet? Totally uninterested in anything I said. Sigh.)

(Oh, and computers in the classroom? Highly distracting. Couple that with networked computers in the classroom, woo boy—just ask my Computer Graphics teacher … on second thought … don't.)


“But it'll be in color!”

From
"Bunny XXXXXXXX" <XXXXXXXXXXXXXXXXXXXXXX>
To
"Sean Conner" <sean@conman.org>
Subject
Wanna talk irony?
Date
Tue, 2 Jan 2007 23:06:43 -0500

I just discovered that the Hallmark Channel is showing M*A*S*H (final episode) which started at 10 p.m. Even if I didn't already have it on tape, I could have taped it for you. You were meant to see it, and I'm pleased to be the one to show it to you.

Guess I'm finally going to see the final M.A.S.H episode afterall.


One funny story about M.A.S.H.—growing up all we had was a small black-and-white TV, so all of my M.A.S.H. viewing was on said set. On the few occasions I've seen M.A.S.H. in color, it just looks … funny. It just … looks weird to me to see M.A.S.H. in color.

And that's the only show that I find weird looking in color. Perhaps because even in color, it's still fairly monochromatic, even if that monochromatic color is green.

Wednesday, January 03, 2007

I've got some good news, and some bad news …

Today felt like one of those Bad News/Good News type of jokes. And it all started out because I needed to modify a client's managed firewall (we manage their firewall).

Bad News: I can't log into the firewall.

Good News: It probably just needs rebooting (which involves walking across the parking lot to another building to the client's office, and flipping a power switch).

Bad News: That didn't work. Perhaps it's the router in the building?

Good News: We have extra ports on that router we can try (which involves making yet another trip to the other building).

Bad News: That still didn't work.

Good News: Which means the router isn't probably at fault.

Bad News: Which means it's the cable that runs from the router to the client's office, or the firewall. Since I have no easy way to test the cable, I'll assume (for now) it's the firewall.

Good News: It's probably a simple configuration setting I forgot to save when setting it up.

Bad News: There's no way to actually log into the firewall at the client's office (doing so requires a terminal or a computer with a serial port and … well … it was probably best not to ask about using a computer with a serial port).

Good News: The firewall itself is pretty small and easy to take back to The Office (which means more schlepping between buildings).

Bad News: When powering up the firewall at my desk, it kernel panics (basically: crashes, and crashes hard) when trying to check the disk.

Good News: Maybe it's just a loose connection.

Bad News: Nope. Still crashes.

Good News: Maybe it just needs some more memory. Here, let's install a 512MB stick of memory.

Bad News: Fails to even do the self test.

Good News: We have plenty of spare Cobalt RaQs (which we use as firewalls) sitting around.

Bad News: Moving the harddrive to another Cobalt RaQ fails to produce any forward results.

Good News: Perhaps if I cannibalize the memory from RaQ I tried to use and put it into the RaQ initially used as the client's firewall.

Good News: There is no more bad news!

Oh wait.

Bad News: Gotta schlep back to the client's office to reinstall the firewall.

Good News: It all now works properly.


“Goodbye, Farewell and Amen”

Bunny made good on her promise, and I saw the final episode of M.A.S.H., almost twenty-four years after it first appeared.

I found it to be excellent (if sad—I mean, it is the end to one of the best series on TV) but a very taxing episode to watch (horrors of war and friends going their own way). I also came to the realization that Charles Emerson Winchester III is one of my favorite characters in the series, trying to maintain his dignity in an undignified location.

Thursday, January 04, 2007

“A student who changes history is probably taking a test.”

Creativity is a weird thing, something I haven't given much thought to to tell you the truth. I've always been creative, and I've managed to surround myself with creative people so it was something that's always there, in the background, something I can pull from, sometimes easily, sometimes not so easily, but I manage to pull something out of the air when the time comes.

And like I said, I've never given it much thought, until I received the following in email from Bunny:

My friend XXX has a son who's been accepted at XXXX XXXXXXX, but needs to do this essay to qualify for a scholarship. I'm really no good at stuff like this. You have any ideas, being creative and all? You have such the imagination! I'm in awe!

Here's what she sent me:

XXXXX has to write a scholarship essay. The prompt is:

A dinner party is a comfortable venue for guests to engage one another in a discussion of ideas. Imagine a dinner party where you could invite any four people, living or dead. Whom would you select and why? What issues or themes would the guests discuss? Answer these questions and develop a portion of the conversation in an essay of no more than 800 words.

He's totally blank. He can think of lots of good people, but can't figure out what they should talk about and how it should be structured. What's the premise, the setup? You can't just jump in and start talking, it wouldn't make sense. He's very uncreative but so am I and I can't think of anything either. He came up with a stinker of an essay that was sort of an allegory tale—World War II Food Fight, where Stalin, Hitler, Churchill and either Mussolini or Hirohito were gathered together and started a food fight that paralleled their battles in the war. But I don't think the prompt wants an allegory, and it wasn't very funny, anyway.

Any ideas?

That forced me to think about creativity, and in the span of maybe twenty minutes or so, I somehow managed to come up with six different groups of people to write about. One of the ideas:

Okay. I might be inclined to do one with just about any four famous people (really, could probably just pick four at random, say, Sean Penn, Karl Marx, Oliver Cromwell and Ayn Rand and just have them complain about the food service, the food itself, and how young kids today just don't know how good they have it—much like the Four Yorkshire Men Sketch from Monty Python).

I'm not sure why exactly I included Sean Penn in the mix (perhaps his self-important goofiness?) but the other three I picked simply because they would hate each other (you'd probably be hard pressed to keep Rand from killing Marx), but then to just have them complain about the service I find terribly funny.

Yes, I do like my humor dry.

Another idea:

Or possibly a dinner conversation between Karl Marx, Vladimir Lenin, Groucho Marx, and John Lennon (with the latter two rubbing the fact they got a stamp together while the other two didn't).

And there is no way that Karl or Lenin would be able to dominate the conversation with Groucho or John in the same room. Oh, to have Lennon tell Lenin to lighten up …

But, again, I certainly can't explain how I came up with these groupings (like the Presidents Andrew Jackson, William McKinley, Franklin Roosevelt and George Bush Jr), other than picking groups of people that would have a complex group dynamic (McKinley and Bush have similar administrations and both got us in unpopular wars, but Bush's cowboy image would certainly not appeal to McKinley, but would appeal to Jackson, but Jackson wouldn't care for Bush or McKinley (or Roosevelt for that matter) because they were city-bred rich folk—dynamics like that). Heck, these groupings almost write themselves.

Perhaps part of it is being well read, and certainly knowing history doesn't hurt matters either.

Anyway, I just find coming up with ideas pretty easy—ooh wait! I know! Three friends grilling George Lucas about Star Wars and what exactly was he smoking when he wrote Episodes 1–3?

See?

I can't exactly say where my creativity comes from, except the few I buy wholesale from Schenectady.

Anyway, some time later Bunny replied to my reply that her friend wrote back with a successful conclusion: saying her son managed to successfully write the essay.

XXX XXXXX XXXXX XXXXX XXXXXX XXXXXXXXXX XXXXXXX XXXX XX XXXX X XXXXXXXX XX XXXX XXX XXXXX XXX XXXXXXXX XXXXXX XXXXXXXX XXXXX XXXXXXX XXXXXXXXXXX XXXXXXXXX XXXXXXXXX XXX XXXXXXXXX XXXXXXX XX X XXXXXX XXXXXX XX XXXXX XXXX XXXX XX XXXXXXXXX XX XXX XXXXX XXXXXX X XXXXX XXXXX XX XXXXX XX XXXX XXX XXXX XXXXXXXX XXX XX XXXX XXXXX XXXXXX XXXXX XXXXX XXXX XX XXXXXXXX XX XXXXXXXX XXXX XXX XXX

XXXXXXXXXXXX XXX XXXX XXXXXXXXXXXX XXX XXXXXXXX XX XXX XXXX XXXXX XXXXXXX X XXXXX XXXXX XXXXXX XXX XXXXX XXX XXXX XXXXX XXX XX XXXXX XX XXXXXX XXXX XXXXXXXXX X XXXXX XX XXXXX XXXX XXXX XXXXXXXXXXXX XXX X XXXX XX XXXXXX XXXX XXXXX XXX XXXX XXX XXXXX XXXXXXXX X XXXXXXX XXXX XXXX XXX XXXXXXX XXXX XX XXXX XXXXXXXX XXXXXX XXX XXXXX XXXX XXXXXXXXXXX XXXXXX XXX XXXXXXX XXXXX XXX XXXXXXXX X XXXXXXXXX XXX X XXXXXXXXX

Update on Friday, January 5th, 2007

Major redaction as you can tell—Bunny's friend requested I remove this material, and since her friend didn't expect this to happen, I'm respecting her friend's wishes.

Friday, January 05, 2007

Redactions

It's always a risk when writing about other people, so it wasn't too surprising when I got the following:

Looking at it further, could you ask him to strike the whole part about who XXXXX decided to write about? I mean, that would point directly to him. I'd really rather not have anything that could possibly identify him out there like that. Tell him sorry, but I'm weird.

in reference to yesterday's entry about creativity (I also had to remove all references to the college as well). And while I may think that Bunny's friend (who requested I remove the material) is being a too cautious, she didn't ask to have the material placed on a website in the first place (even though I thought I removed enough identifying material).

It's not like this hasn't happened before.

Bunny had written me earlier about removing some information (before she wrote me asking for a whole bunch more stuff to be removed):

Hey, here's something that didn't occur to me. XXX says they check the internet for plagiarism and stuff, and [the college] might google and find your post. Not likely, but do you think you could strike the reference to [the college], just in case? … I know they wouldn't stumble upon it just by the premise for the essay alone. … I can't imagine they have a filter or something set up to ring a chime every time somebody mentions [the college]. But I guess she'd feel better about it. She loved your stories and creativity, though, and wished she'd asked me sooner.

While [the college] itself might not actually check, there are other services that do, and one such service (if not the service) is TurnItIn. So, it is conceivable that [the college] could come across these entries (although I thought that I made it clear that I did not come up with the kid's essay idea, but hey, things I wrote a long time ago have a habit of resurfacing), but whether it will hurt the kid? I doubt it, but hey, like I said, the kid's mother didn't ask for this to be posted, so best to remove it (am I making a mountain out of a molehill? I don't think so—it's just something I can write about, that's all).

Saturday, January 06, 2007

“You know, melting coins for the intrinsic metalic value is now illegal in the United States.”

I was going through my change in the car today when I found this nickel and while the front is typical, it was the back that caught my eye—it looks partially melted. It's not been shot, that would have deformed the coin and this is still quite normally flat. I doubt it's an arc-welder as the front is still fine, and there don't appear to be any scorch marks along the back.

Perhaps acid?

Anyway, it's pretty cool looking.

Sunday, January 07, 2007

Been busy with other stuff, so this is what you get for today.

I spent some time today fixing the mailing list software so it no longer breaks MIME based emails. The software is old, but it has two features I like: the software is straightforward and it's easy to maintain.

I'm not sure why I took as long as I did to fix it—perhaps it's due to my own relunctance towards MIME (“Email is not for file transfers! That's what FTP is for!”) or some form of passive-aggressive attack on my part to show just how bloated HTML email can be (“FTP people! FTP!”). Although once I figured out which headers I needed to preserve (not as many as I feared) it was pretty easy to patch the software.

Monday, January 08, 2007

Jesse has left the planet

I just had a funny thought: There have been numerous sightings of Elvis since his death in 1977, but not one recorded sighting of Elvis' twin brother, Jesse since his death in 1935.

Why is that?

Tuesday, January 09, 2007

Ideas for features for my blogging software

The goal last time was a macro processor. I write a lot of math articles. I get tired of writing <sup>2</sup> every time I want a superscript 2. Even if I bind a function key to that sequence of characters, it's hard to read. But now, with my new Blosxom macro processor, I just insert a line into my article that says:

#define ^2 <sup>2</sup>

and for the rest of the article, ^2 is expanded to <sup>2</sup>.

The world's worst macro preprocessor

This is, without a doubt, an incredible idea and one I wish I had thought of. I already use shortcuts like this, such as “---” for “—” (an em-dash) or “``” for the nice open double quote that are “baked” into the code so to speak, but the ability to add more on a per-entry basis would be very neat indeed.

I'll have to look into this a bit more.

Wednesday, January 10, 2007

Oh, so that's what an ssh scanner looks like

Between metro ethernet woes and a customer's server either attacking other machines, or being attacked by other machines (it was never made clear in what direction the excessive network traffic was travelling), I was made aware that one of our servers was generating a large amount of outgoing ssh traffic.

When I logged in, sure enough, one ps aux code later:

rob      30289  0.0  0.0  8632 2284 pts/1    S    10:53   0:00 ./ssh-scan 100

Only, about four score and seven more copies than the one just listed there. It looks like regular user accounts were compromised (it's a dedicated server to one of our clients so we don't have full control over it). Not much else to do but kill off the offending processes (and finding a second compromised account running an IRC bot), locking out the account and looking at said ssh-scan program.

Interesting stuff—found one file named vuln.txt that seemed to have a list of servers with default accounts and passwords.

Hmmmm …

I tried one system listed in the vuln.txt file and got the following:

-------------------------
Mitel Networks SME Server
-------------------------


Standard user login services have been disabled.


Type "end" and press ENTER to terminate this connection: 


I tried another vulnerable system, and was able to actually get a shell:

[spc]shell:~>ssh tester@XXXXXXXXXXXXXX
tester@XXXXXXXXXXXXXX's password: 
-bash-2.05b$ 

But when I tried to actually use system, it was rather limited. The only commands available were ls, mkdir, mv, pwd, rm, sh, groups, id, ssh and bash and a bunch of builtin shell commands.

Makes it kind of hard to look around, but with discussion with an unnamed friend of mine, we came up with the following to actually view the few files that existed on this system:

(while true ; do read && echo $REPLY ; done) <filename

I'm beginning to think these ssh scans aren't for vulnerable Unix systems, but embedded systems with manufacterer backdoors built in that a certain clientel of user are using to their own nefarious schemes.

Thursday, January 11, 2007

More musings on Star Wars

If we accept all the Star Wars films as the same canon, then a lot that happens in the original films has to be reinterpreted in the light of the prequels. As we now know, the rebel Alliance was founded by Yoda, Obi-Wan Kenobi and Bail Organa. What can readily be deduced is that their first recruit, who soon became their top field agent, was R2-D2.

Via Jason Kottke, A New Sith, or Revenge of the Hope Reconsidering Star Wars IV in the light of I- III

An interesting reinterpretation of Star Wars IV–VI, notwithstanding the fact that George Lucas was making everything up as he went along, especially for episodes I–III but he doesn't care—he's got our money and besides, geeks live for explaining continuity errors in science fiction series (and amusingly enough, nothing that went on in Episodes I–III matched what he wrote about in “Bantha Tracks”—I know this because my friend Hoade used to get this newsletter as a kid).


I just like the quote.

“It's got kind of a slacker appeal, a no-resistance story line.” Animators and children's TV creators around the world must see Scooby and ask themselves: Why can't my crappy show become iconic?

Dog Gone: Scooby-Doo creator Iwao Takamoto died this week, but his legacy lives on.

But it wasn't as if the creators of Scooby-Doo were perfect— far from it and I can prove it with one word (or is it two?):

Scrappy-Doo.

But despite that, Scooby-Doo did reach iconic status.

Somehow.


Sorry, English speakers need not ride

ST. PAUL, Minn. (AP)—A school bus driver let Rachel Armstrong's three children board the bus Monday morning, but he warned them that he wouldn't give them a ride home that afternoon, nor could they ever ride his route again.

The problem: Armstrong's 10-year-old twin girls and 8-year-old son speak English. According to their mother, the driver told them the route had been designated for non-English speakers only.

Via Gates of Vienna, Students kept from bus in St. Paul; told reserved for those learning English

Has desegregation busing gotten such a bum rap that the pendulum has swung around again? Have we gone back to “separate but equal”?

Why didn't I get the memo?

Was there a memo?

I'm horribly confused.

Friday, January 12, 2007

Bug hunt

It wasn't so easy to patch.

Email headers can technically span multiple lines, although the mailing list software I'm using doesn't actually support headers that span multiple lines.

And thus breakage.

The email I sent to the affected mailing list I run went into a bit more detail (more, I'm sure, than the members cared to know):

From
Sean Conner <sean@conman.org>
To
XXXXXXXXXXXXXXXX
Subject
[dss] Mailing list woes
Date
Fri, 12 Jan 2007 16:43:02 -0500 (EST)

Okay, you didn't ask for it, but you got it anyway.

What exactly was going on with the mailing list software, and why were the messages so funky to begin with?

The mailing list software I'm using has a few features that I like:

  1. it's simple.
  2. it's simple to install (this is a very important part).
  3. it works.

I started using it back in the mid-90s but I think it's a few years older than that even. It was written way back before there existed a stardardized method for sending files via email [1], so it never had the ability to handle attachtments, nor, as it turned out, HTML formatted email.

In the mid-90s, a standard was created for the sending of multi-media based emails—MIME. Not only did it allow a way to send attachtments, but it also allowed email messages to contain both a plain text version and a formatted version of an email (say, using HTML or even Microsoft Word Doc). This was done by adding some extentions to the headers of the email, which change the way the email client processes the body of the message.

The mailing list software, did not know about these headers, so it didn't preserve these headers and thus, you got funky looking email. [2]

So all I needed to do was preserve the required headers and bam! The mailing list software would automatically support all this MIME crap [7] and everybody would be happy and be able to actually read the messages.

Only, preserving said lines wasn't as easy as I expected.

You see, the headers in an email message are name/value pairs:

From
Lorie Davis <XXXXXXXXXXXXXXXXXXXXX>
To
The Dragonslayers Society <XXXXXXXXXXXXXXXX>
Subject
Are we done yet?
Date
Fri, 12 Jan 2007 16:43:02 -0500

but the email standard states that a header can actually span multiple lines:

From
Lorie Davis <XXXXXXXXXXXXXXXXXXXXX>
To
The Dragonslayers Society <XXXXXXXXXXXXXXXX>
Subject
Have you finished using me as an example?
Mime-Version
1.0
Content-Type
multipart/alternative;
boundary="—-=_Part_44704_28465339.1168636054704"
Date
Fri, 12 Jan 2007 16:07:34 -0500

(note how the Content-Type header spans multiple lines) Now, not all headers span multiple lines, but it is allowed by the email standard. But the mailing list software didn't allow for multiple lines per header, and for the headers it was originally interested in, were never really split across multiple lines.

I found this out the hard way.

The way the code was originally written made it difficult (read: damn near impossible) to support multiline headers. So it required a bit of rewriting to make this all work.

So, why not just install some modern mailing list software? See rule #2 above? Have you seen what's required to install modern mailing list software? At least a 2GHz machine to start off with. A score of libraries. And now I'm treading into the scripting lauguage du jour as well.

Believe me, it was easier to patch the existing mailing list software than to install something new (which basically, would require updating my entire server, which is something I refuse to do, seeing how it works and is secure as is—and I'll stop here before I start ranting on the whole upgrade culture).

-spc (Who still uses 486s)

  1. EMAIL is NOT FTP!

    Sorry.

    I was never one for sending files via email, as there are better, more efficient and faster ways of doing that. What no one (and by “no one” I mean those that aren't programmers) seems to realize that when you send a file through email, the file has to be converted to text, least a lot of email software along the way blows up. This conversion process inceases the file size by at least a third (so a file that's 3M now becomes an attachtment 4M in size).

    But it's damned convenient [3][5], so everybody does it.

    Well, except me. But I'm not your typical user to begin with.

    Anyway …

  2. Not that I minded—that's how I receive such messages, even though my the email client I now use understands the MIME headers. Yes, what you were seeing was the raw message body itself, in all its bloated HTML glory that every email client seems to bloody default to these days [3].
  3. Thank you so very much, Microsoft. [4]
  4. May you rot in Hell.
  5. Thank you so very much, University of Washington. [4][6]
  6. http://en.wikipedia.org/wiki/Pine_(e-mail_client)
  7. That's a technical term.

If I come across as a curmudgeon, then yes, I don't like the fact that people send files via email (reguardless of how convenient it is) nor do I like HTML formatted email (if plain text is good enough for me, then gosh darn it's good enough for you!) so quite a bit of this is just me blowing off some steam.

Saturday, January 13, 2007

Notes on some programming postulates

During a lull in the D&D game last night, I was doing the programmer equivalent of doodling, engaging in one of my interests—programming language design. Old interests die hard, and this, along with operating system design, are very old, dating back to high school. Bunny asked what I was doing, and I quickly got self-conscious.

It happens when one is caught doodling.

Afterwards in discussing this, I mentioned some postulates I have about programming; I don't feel it's anything earth shattering, but pondering on them (and I've been pondering on them for a few years now) has lead to some interesting questions.

The first one, which I tend to think of as number zero (which, in programming circles, makes some sense), is: a program is a subroutine writ large.

Now, I'm using some very loose definitions of “program” and “subroutine” here. By “subroutine” I mean any sequence of code that does “something” and can be called one or more times. By “program” I mean any sequence of code that does “something” and can be run by the user. So really, except for the context in which it is used, a “subroutine” and a “program” aren't much different (and in fact, on some platforms like Microsoft Windows, you can treat a program like Microsoft Internet Explorer, for instance, as a subroutine to be used by a program you write).

So, the next three postulates. For each of these, when you see the term “subroutine” you can also substitute the term “program” without any change in meaning.

  1. A subroutine may accept input.
  2. A subroutine may do processing.
  3. A subroutine must produce output.

It was fun coming up with this list. The first version of the first postulate was “a subroutine must have input” which I then had to think if there were any types of subroutines that violated this.

And there were. A program to calculate e to 100,000 digits, the Unix utility yes and any number of utilties to overwrite files with meaningless data. There are a class of programs that can very well deal without any input whatsoever. So input is optional.

And the second one was similar: “a subroutine must do processing.” But the definition of “processing” is a bit thorny—take the Unix utility yes, which just repeatedly spits out lines consisting of a single “y” (you use it to automatically respond “yes” to other Unix utilities, like fsck). I have a hard time with the notion of it doing any “processing”. I mean, the code is little more than:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
  while(1)
    printf("y\n");
  return (EXIT_SUCCESS); /* not that it ever exits */
}

While technically there is processing going on, i.e. the CPU is processing instructions, it's not actually calculating. Yes, what it does is useful, but is it “processing?”

I wouldn't classify this as “processing” for the types of “processing” I'm thinking of, so postulate number two—a program must do processing, must be wrong. It may do processing.

It's the third one, “a subroutine must have output,” that has given me the most problems.

At first, I had a real hard time coming up with examples of a subroutine that had no output. I mean, why even bother calling a subroutine that had absolutely no output? What exactly, would be the point? I was about to conclude that all subroutines must have output, when I remembered writing just such a subroutine for my first computer, a Tandy Color Computer.

A small digression: The Color Computer technically had a serial port, in that there is a one bit input port and a one bit output port which is driven entirely by software. To send a byte, you drive the output port low for X µseconds, then set the port to match the first bit, wait X µseconds, then set the port to match the second bit, wait X µseconds, and so on, where X is a value dependent upon the baud rate. And I ended up writing code to drive the “serial port” on the Color Computer. And as part of this, I had the following subroutine:

DELAY	PSHS	X,CC
	LDX	#413
DELAY10	LEAX	-1,X
	BNE	DELAY10
	PULS	X,CC,PC

This would delay 3.3 milliseconds, giving me a baud rate of 300bps.[1] The X register, as well as the condition codes, are saved, so the effect of this routine on the CPU state was nil. The only difference between:

NOP		* NO OPERATION

and

BSR	DELAY	* NO OPERATION, BUT A LONG DELAY

was 3,331 µseconds (NOP requiring 2 µseconds to execute).

Well. [Deep subject. —Editor]

Here I have, from my own archive, a subroutine that takes no input, does no real processing, and has no output.

And yet it's a useful subroutine.

Granted, it appears to be an exception to the rule that all subroutines must have output. And really, these days, the majority of programmers don't go about writing delay loops like this. Nope, they make calls to sleep() which … um … causes the program … to … um … delay … for a period of time.

Well … um …

But …

But it seems wrong to conclude that subroutines may have output. Because outside of a few esoteric subroutines like my DELAY routine, or sleep(), a subroutine must have output or else, why bother calling it?

How to reconcile this?

How indeed.

But what if I now ask the question: “What is output?”

In the case of DELAY, I'm calling the subroutine not for any tangible result, but for the side effect of doing nothing for 3,333 µseconds. And in general, output is a type of side effect (as any functional programmer will tell you), since output affects the state of the program (outputing a “y”, followed by a second “y” changes some state somewhere, if only to advance the printing location of subsequent characters).

So, if side effects are considered a type of output, and DELAY has a side effect, then it can be considered to have output, so now I don't have to reconcile anything—subroutines must have output.

Like I said, it was nothing earth shattering here, but even Euclid started from a simple straight line [2] and from there expanded upon geometry.

  1. Actually, this code assumes a 1MHz clock rate on the CPU. The actual clock rate on the Computer Computer was 0.89MHz, but I used 1MHz for this example to make the math easier on me.
  2. Although you start getting odd results when you question the nature of a straight line.

Sunday, January 14, 2007

Some musings on coroutines

Over a year ago, having nothing else better to do (seeing how the power was out), I did some research into co-routines. I figure now is as good a time as any to talk about some conclusions I came to (seeing how all that programming talk yesterday is inspiring).

Subroutines are special cases of more general program components, called “coroutines.” In contrast to the unsymmetric relationship between a main routine and a subroutine, there is complete symmetry between coroutines, which call on each other.

To understand the coroutine concept, let us consider another way of thinking about subroutines. The viewpoint adopted in the previous section was that a subroutine merely was an extension of the computer hardware, introduced to save lines of coding. This may be true, but another point of view is possible: We may consider the main porogram and the subroutine as a team of programs, with each member of the team having a certain job to do. The main program, in the course of doing its job, will activate the subprogram; the subprogram performs its own function and then activates the main program. We might stretch our imagination to believe that, from the subroutine's point of view, when it exits it is calling the main routine; the main routine continues to perform its duty, then “exits” to the subroutine. The subroutine acts, then calls the main routine again.

This somewhat far-fetched philosophy actually takes place with coroutines, when it is impossible to distinguish which is a subroutine of the other. Suppose we have coroutines A and B; when programming A, we may think of B as our subroutine, but when programming B, we may think of A as our subroutine. … It represents teamwork as in a relay race. Whenever a coroutine is activated, it resumes execution of its program at the point where the action was last suspended.

The Art of Computer Programming, § 1.4.2

When researching just about anything dealing with computers, it's probably best to start with the source, Donald Knuth. § 1.4.2 covers the basics of coroutines and gives an example, which would look something like this (when converted from MIX assembly, used for all the examples in the book, to a C-like langauge, which is a bit easier to understand):

int input(void)
{
  int c;

  while(1)
  {
    c = getchar();
    if (isdigit(c))
    {
      int count = c - '0' + 1;
      c = getchar();
      for ( ; count ; count--)
        yield to output(c);
    }
    else
      yield to output(c);
    if (c == '.')
      return;
  }
}

void output(int c)
{
  int count = 0;
  int c;

  while(1)
  {
    yield to c = input();
    putchar(c);
    if (c == '.')
      return;
    count++;
    if (count == 3)
    {
      putchar(' ');
      count = 0;
    }
  }
}

The thing to understand about coroutines is that it isn't a normal subroutine call. Normally, each time input() is called, control is passed to the first line of the routine, but in a coroutine “call,” control is initially passed to the first line, but each subsequent “call” resumes where input() left off (in this case, marked with the keyword yield). If we change the code a bit (remember, this isn't C, but a C-like langauge), this can become clearer:

void input()
{
  while(1)
  {
    c = getchar();
    if (isdigit(c))
    {
      int count = c - '0' + 1;
      c = getchar();
      for ( ; count ; count--)
        send c to output;
    }
    else
      send c to output;
    if (c == '.')
      return;
  }
}

void output()
{
  int count = 0;
  int c;

  while(1)
  {
    receive c from input;
    putchar(c);
    if (c == '.')
      return;

    count++;
    if (count == 3)
    {
      putchar(' ');
      count = 0;
    }
  }
}

Here, it should be a bit clearer what is going on—input() is getting some data, then passing it to the coroutine output(). I've changed the way that coroutines are “called” for two reasons. One, it's a bit clearer what is going on, and two, there's a bit more going on here than just very fancy gotos. In § 1.4.2, Knuth gives the following illustration (recreated here):

[Fig. 22 from § 1.4.2 of “The Art of Computer Programming”]

Passes: (a) a four-pass algorithm, and (b) a one-pass algorithm.

Those familiar with Unix should see a familiar pattern here:

GenericUnixPrompt> pass-a <input >tape.1
GenericUnixPrompt> pass-b <tape.1 >tape.2
GenericUnixPrmpot> pass-c <tape.2 >tape.3
GenericUnixPrompt> pass-d <tape.3 >output

Or, more succinctly:

GenericUnixPrompt> pass-a < input | pass-b | pass-c | pass-d >output

Coroutines are nothing more than routines that communicate via pipes! A type of message passing, if you will.

Not only that, but given the rise of multi-core processors, this appears to be a natural fit for multithreaded programs. A piped Unix command line uses a separate process for each component, so it appears to be a no-brainer that each component in a coroutine chain can be given its own thread. With that, and some syntactic help, we can rewrite Knuth's example and extend it a bit:

void input()
	receive char;
	send    char;
{
  char c;

  while(1)
  {
    receive c;
    if (isdigit(c))
    {
      int count = c - '0' + 1;
      receive c;
      for ( ; count ; count --)
        send c;
    }
    else
      send c;
    
    if (c == '.')
      return;
  }
}

void output()
	receive char;
	send    char;
{
  int  count = 0;
  char c;

  while(1)
  {
    receive c;
    send c;
    if (c == '.')
      return;

    count++;
    if (count == 3)
    {
      send ' ';
      count = 0;
    }
  }
}

void filter(char from,char to)
	receive char;
	send	char;
{
  while(1)
  {
    accept c;
    if (c == from)
      c = to;
    send c;
  }
}

int main(void)
{
  string in;
  string out;

  in = get_input();
  in => input() 
     => filter('a','n') 
     => filter('e','x') 
     => output() => out;
  print(out);
}

Coroutines make the same fringe problem trivial to implement:

void tree_leaves(Tree t)
	send Tree;
{
  if (t == nil)
    send nil;
  if (is_leaf(t))
    send t;
  send tree_leaves(t->left);
  send tree_leaves(t->right);
}

bool same_fringe(Tree t1,Tree t2)
{
  Tree tmp1;
  Tree tmp2;

  while
  (
  	(tree_leaves(t1) => tmp1)
    &&	(tree_leaves(t2) => tmp2)
  )
  {
    if (tmp1 != tmp2)
      return (false);
  }
  return true;
}

There are even more implications here. The producer/consumer problem is one used to teach semaphores, but with coroutines, it becomes rather trivial:

void producer()
	send	datum;
{
  datum data;

  while(1)
  {
    data = generate_datum();
    send data;
  }
}

void consumer()
	receive	datum;
{
  datum data;

  while(1)
  {
    receive data;
    crunch_datum(data);
  }
}

producer() <=> consumer();

Even with multiple consumers, I don't see a problem with this model:

producer() <=> (consumer(), consumer());

And other problems used to teach semaphores, like the multiple-reader, exclusive writer problem, become trivial:

void master_control_program()
	receive	command;
	receive datum;
	send datum;
{
  command cmd;
  datum   data;

  while(1)
  {
    accept cmd;
    if (cmd == read)
      send data;
    else if (cmd == write)
      receive data;
  }
}

void reader(int id)
{
  datum data;

  while(1)
  {
    send read;
    receive data;
    process(data,id);
  }
}

void writer(int id)
{
  datum data;

  while(1)
  {
    sleep(random());
    data = generate_datum(id);
    send write;
    send data;
  }
}

master_control_program() <=> (	reader(1),
				reader(2),
				reader(3),
				writer(1),
				reader(4),
				writer(2),
				writer(3),
				reader(5));

But in retrospect, this is nothing more than a reinvention of communicating sequential processes, and what I've managed to do is basically hide message passing within the framework of coroutines, which is why I suddenly found myself easily solving problems that normally require semaphores.

Granted, there aren't any langauges that do this sort of thing (well, there is Erlang, but it's a functional language, not imperative like C or C++), and if I were to implement a language with coroutine support like this, there are still issues of implementation and syntax to work out, but I'm still playing around with this stuff for now.

Monday, January 15, 2007

A holiday again?

Wlofie asked if I could give him a ride to the bank and the the post office (he needed a stamp to send in a rebate claim). No problem. We head out and arrive a few minutes later at the bank.

You know, these holidays have a way of sneaking up on us.

No bank. No post office.

But hey, for civil rights, that's fine by me.


Some more musings on programming, given the recent spate of entries on the topic

Patterns are signs of weakness in programming languages.

When we identify and document one, that should not be the end of the story. Rather, we should have the long-term goal of trying to understand how to improve the language so that the pattern becomes invisible or unnecessary.

Design patterns of 1972

While I've heard of the Gang of Four and their book, Design Patterns, I've never quite understood all the hoopla over it—the whole concept seemed pretty silly, or too obvious, to warrant a whole book on the subject. And it seems like I'm not the only one to think that as well, and I agree with the author, design patterns are silly.

Tuesday, January 16, 2007

Captain Napalm's Thermonuclear League of Liberty

From
XXXXXXXXXXXXXXXXXXX
To
sean@conman.org
Subject
Captain Napalm's Thermonuclear League of Liberty
Date
Tue, 16 Jan 2007 10:16:38 -0500

So how do I join and get my very own thermonuclear weapons to play with?

About ten years ago, during one of my site redesigns, I embedded the following in an HTML comment on each page:

Join Captain Napalm's Thermonuclear League of Liberty …
write sean@conman.org for details …

That very same comment was even carried over to my blog—go ahead, check the source code and see. I'll wait.

Back?

Today was the first time anyone bothered to write about joining Captain Napalm's Thermonuclear League of Liberty (and it was my old roommate Rob who wrote in).

And it's been so long since I added it, I have no idea what exactly to do.

Other than maybe change the comment and see if it takes less than ten years for anyone else to notice.

Wednesday, January 17, 2007

The lost continent of Africa

Bunny was showing me some brochures for Florida attractions around Lake Okeechobee (most of which I missed seeing on the trip to Bok Tower) when I remembered Africa USA, an attraction, long since gone, was located in Boca Raton.

From the one aerial shot (which is oriented such that west is along the top edge) and some supplementary data, I was able to locate where Africa USA was located (I had originally thought it was a bit further south, at the intersection of 18th and Old Dixie Highway). It is now, of course, a large development of condos and single family homes.

While looking for the location of Africa USA, I was once again reminded of a long lost theme park I've come across, this time in Pompano BeachStoryland, another attraction from the the 50s. This one was a bit easier to locate, given both the aerial shot and address. It is now, of course, a large strip mall (and I wonder if this Storyland is at all related to the former Storyland in Pompano Beach).

Thursday, January 18, 2007

Yeah, I know the feeling …

[The task I must undertate is towering over me like a great big monolith.  It is too big to contemplate, so I think I will go and have a little look at the Internet.]

(Via The Adventures of Accordion Guy in the 21st Century)

Friday, January 19, 2007

Don't think this'll happen any time in the near future.

Five years later and the weather hasn't changed as much as it has in 30 years.

Go figure.


A quick note on embedding languages within languages

While I don't fully agree with this article (link via ThoughtStorms, and more on this in a later entry) I do agree that our current methods of programming do fall short (design patterns being silly). This was made plainly apparent today at The Office.

I have this program called ospfquery that not only retrieves OSPF specific SNMP data, but can also dump a routing table from a router.

  Dest           Mask           NextHop         Proto   Metric Age
-------------------------------------------------------------------------------
169.254.0.0     255.255.0.0     XXXXXXXXXX.5    ospf    1     334866
172.16.0.0      255.240.0.0     XXXXXXXXXX.5    ospf    1     334866
192.0.2.0       255.255.255.0   XXXXXXXXXX.5    ospf    1     334866
192.168.0.0     255.255.0.0     XXXXXXXXXX.5    ospf    1     334866
198.18.0.0      255.254.0.0     XXXXXXXXXX.5    ospf    1     334866

But it doesn't quite work with Riverstones:

  Dest           Mask           NextHop         Proto   Metric Age
-------------------------------------------------------------------------------
1.0.0.0         32.161.7.0      26.127.177.69   ???     159791312426295

It's clear that the Riverstone doesn't support the right SNMP MIBs that ospfquery uses to retrieve the routing table. But by dumping the entire SNMP tree, I was able to find equivalents.

Routing table SNMP MIBs for Cisco and Riverstone
CiscoRiverstone
RFC1213-MIB::ipRouteDest IP-MIB::ip.24.4.1.1
RFC1213-MIB::ipRouteMask IP-MIB::ip.24.4.1.2
RFC1213-MIB::ipRouteNextHop IP-MIB::ip.24.4.1.4
RFC1213-MIB::ipRouteProto IP-MIB::ip.24.4.1.7
RFC1213-MIB::ipRouteAge IP-MIB::ip.24.4.1.8
RFC1213-MIB::ipRouteMetric1 IP-MIB::ip.24.4.1.11
RFC1213-MIB::ipRouteType IP-MIB::ip.24.4.1.6

So, on to the code:

oid objid_ipRouteDest[] = {1, 3, 6, 1, 2, 1, 4, 21, 1, 1};
int length_ipRouteDest = sizeof(objid_ipRouteDest)/sizeof(oid);
oid objid_ipRouteMetric1[] = {1, 3, 6, 1, 2, 1, 4, 21, 1, 3};
int length_ipRouteMetric1 = sizeof(objid_ipRouteMetric1)/sizeof(oid);
oid objid_ipRouteNextHop[] = {1, 3, 6, 1, 2, 1, 4, 21, 1, 7};
int length_ipRouteNextHop = sizeof(objid_ipRouteNextHop)/sizeof(oid);
oid objid_ipRouteType[] = {1, 3, 6, 1, 2, 1, 4, 21, 1, 8};
int length_ipRouteType = sizeof(objid_ipRouteType)/sizeof(oid);
oid objid_ipRouteProto[] = {1, 3, 6, 1, 2, 1, 4, 21, 1, 9};
int length_ipRouteProto = sizeof(objid_ipRouteProto)/sizeof(oid);
oid objid_ipRouteAge[] = {1, 3, 6, 1, 2, 1, 4, 21, 1, 10};
int length_ipRouteAge = sizeof(objid_ipRouteAge)/sizeof(oid);
oid objid_ipRouteMask[] = {1, 3, 6, 1, 2, 1, 4, 21, 1, 11};
int length_ipRouteMask = sizeof(objid_ipRouteMask)/sizeof(oid);


void collect_route_table(ss)
struct snmp_session *ss;
{
  struct ospfRT *cur;
  struct snmp_pdu *pdu, *response;
  struct variable_list *vars;
  int	    good_var, index;
  int	    status, count;

  pdu = snmp_pdu_create(GETNEXT_REQ_MSG);

  snmp_add_null_var(pdu, objid_ipRouteDest, length_ipRouteDest);
  snmp_add_null_var(pdu, objid_ipRouteMetric1, length_ipRouteMetric1);
  snmp_add_null_var(pdu, objid_ipRouteNextHop, length_ipRouteNextHop);
  snmp_add_null_var(pdu, objid_ipRouteType, length_ipRouteType);
  snmp_add_null_var(pdu, objid_ipRouteProto, length_ipRouteProto);
  snmp_add_null_var(pdu, objid_ipRouteAge, length_ipRouteAge);
  snmp_add_null_var(pdu, objid_ipRouteMask, length_ipRouteMask);

  good_var = 7;
  while(good_var == 7){
    good_var = 0;
    status = snmp_synch_response(ss, pdu, &response);
    if (status == STAT_SUCCESS){
      if (response->errstat == SNMP_ERR_NOERROR){
	pdu = snmp_pdu_create(GETNEXT_REQ_MSG);

	index = 0;
	if (rtp == (struct ospfRT *) 0) {
	    rtp = (struct ospfRT *) malloc(sizeof(struct ospfRT));
	    cur = rtp;
	    cur->prev = (struct ospfRT *) 0;
	}
	else {
	    cur->next = (struct ospfRT *) malloc(sizeof(struct ospfRT));
	    cur->next->prev = cur;
	    cur = cur->next;
	}
	cur->next = (struct ospfRT *) 0;
	for(vars = response->variables; vars; vars = vars->next_variable) {
          if (index == 0 && vars->name_length >= length_ipRouteDest &&
              !bcmp((char *)objid_ipRouteDest, (char *)vars->name,
              sizeof(objid_ipRouteDest))){
                cur->ipRouteDest = *vars->val.integer;
                snmp_add_null_var(pdu, vars->name, vars->name_length);
                good_var++;
          } else if (index == 1 && vars->name_length >= length_ipRouteMetric1 &&
                     !bcmp((char *)objid_ipRouteMetric1, (char *)vars->name,
                     sizeof(objid_ipRouteMetric1))){
            cur->ipRouteMetric1 = *vars->val.integer;
            snmp_add_null_var(pdu, vars->name, vars->name_length);
            good_var++;
          } else if (index == 2 && vars->name_length >= length_ipRouteNextHop &&
                     !bcmp((char *)objid_ipRouteNextHop, (char *)vars->name,
                     sizeof(objid_ipRouteNextHop))){
            cur->ipRouteNextHop = *vars->val.integer;
            snmp_add_null_var(pdu, vars->name, vars->name_length);
            good_var++;
          } else if (index == 3 && vars->name_length >= length_ipRouteType &&
                     !bcmp((char *)objid_ipRouteType, (char *)vars->name,
                     sizeof(objid_ipRouteType))){
              cur->ipRouteType = *vars->val.integer;
              snmp_add_null_var(pdu, vars->name, vars->name_length);
              good_var++;
          } else if (index == 4 && vars->name_length >= length_ipRouteProto &&
                     !bcmp((char *)objid_ipRouteProto, (char *)vars->name,
                     sizeof(objid_ipRouteProto))){
            cur->ipRouteProto = *vars->val.integer;
            snmp_add_null_var(pdu, vars->name, vars->name_length);
            good_var++;
          } else if (index == 5 && vars->name_length >= length_ipRouteAge &&
                     !bcmp((char *)objid_ipRouteAge, (char *)vars->name,
                     sizeof(objid_ipRouteAge))){
            cur->ipRouteAge = *vars->val.integer;
            snmp_add_null_var(pdu, vars->name, vars->name_length);
            good_var++;
          } else if (index == 6 && vars->name_length >= length_ipRouteMask &&
                     !bcmp((char *)objid_ipRouteMask, (char *)vars->name,
                     sizeof(objid_ipRouteMask))){
            cur->ipRouteMask = *vars->val.integer;
            snmp_add_null_var(pdu, vars->name, vars->name_length);
            good_var++;
          }
          index++;
        }
      } else {
        printf("Error in packet.\nReason: %s\n", snmp_errstring(response->errstat));
        if (response->errstat == SNMP_ERR_NOSUCHNAME){
          printf("This name doesn't exist: ");
          for(count = 1, vars = response->variables; vars && count != response->errindex;
              vars = vars->next_variable, count++)
			    ;
          if (vars)
            print_objid(vars->name, vars->name_length);
          printf("\n");
        }
      }

    } else if (status == STAT_TIMEOUT){
      printf("No Response from router\n");
      exit(1);
    } else {    /* status == STAT_ERROR */
      printf("An error occurred, Quitting\n");
      exit(2);
    }

    if (response)
      snmp_free_pdu(response);
  }
    /* get rid of last element that contains garbage. */
    /* this loop is ugly and copied from CMU. It needs rewritten */

  if (cur->prev) {
    cur->prev->next = (struct ospfRT *) 0;
    free(cur);
  }
}

Um … yeah … (and that's before adding support for the other set of SNMP MIBs)

Ideally, I'd love do to something like:

OID sys = SNMPv2-MIB::sysObjectID.0;
  
if (sys == SNMPv2-SMI::enterprises.5567.1.1)  /* riverstone */
{
  IpAddress destination[] = IP-MIB::ip.24.4.1.1;
  IpAddress mask[]        = IP-MIB::ip.24.4.1.2;
  IpAddress nexthop[]     = IP-MIB::ip.24.4.1.4;
  int       protocol[]    = IP-MIB::ip.24.4.1.7;
  int       age[]         = IP-MIB::ip.24.4.1.8;
  int       metric[]      = IP-MIB::ip.24.4.1.11;
  int       type[]        = IP-MIB::ip.24.4.1.6;
}
else if (sys == SNMPv2-SMI::enterprises.9.1)  /* cisco */
{
  IpAddress destination[] = RFC1213-MIB::ipRouteDest;
  IpAddress mask[]        = RFC1213-MIB::ipRouteMask;
  IpAddress nexthop[]     = RFC1213-MIB::ipRouteNextHop;
  int       protocol[]    = RFC1213-MIB::ipRouteProto;
  int       age[]         = RFC1213-MIB::ipRouteAge;
  int       metric[]      = RFC1213-MIB::ipRouteMetric1;
  int       type[]        = RFC1213-MIB::ipRouteType;
}

for (i = 0 ; i < destination.length; i++)
{
    print(
        destination[i],
        mask[i],
        nexthop[i],
        snmp.protocol(protocol[i]),
        metric[i],
        age[i]
    );
}

I would love to make SNMP queries like this, but the ability to embed a secondary language within another language is difficult at best. I do recall in college, I seem to dimly recall the ability to embed SQL within C (or was is Pascal? It was on the VAX system). Something like:

int authenticate(char *user,char *password)
{
  dbpass = ~~ SELECT password 
		FROM g_database.users 
		WHERE user="%user%" ~~;

  if (dbpass == NULL)
    return (FALSE);
  rc = (strcmp(dbpass,password) == 0);
  free(dbpass);
  return (rc);
}

Much easier than building SQL strings and hoping you get the quoting right.

But alas, such tools and/or languages don't exist (or have ceased to exist) and I'm stuck patching this program to support an alternative set of SNMP MIBs to pull the routing table from Riverstones.

Upate on Thursday, July 22nd, 2010

I found a way to do what I wanted

Saturday, January 20, 2007

Reference materials

Since Bunny was curious about this, here goes.

I generally do the highly technical (of somewhat long) entries from home, where access to reference materials are very close at hand (usually, behind me, although occasionally across the room). This is important because I try to make them as accurate as possible; it's usually the small details that count (like in yesterday's entry where the code sample of how I'd like to read SNMP variables has a bug that would probably prevent it from compiling if indeed, I could compile such code—I'll leave it as an exercise for the reader to find it).

And some posts require a fair bit of reference material.

[This is six inches of reference material right here]

The above photo is the reference material for a post I'm working on, which is related to the one I made about coroutines, but this time, goes into details about various methods of passing data between routines (and in case you can't make it out, that slim black volume in the middle is QNX System Architecture, and yes, the VAX, the Amiga, the Motorola 68K family, and QNX are all related in a James Burkeian way that I hope to explore in a future entry).

Yes.

Parameter passing.

It should be noted that this blog serves a purpose for me, that is, it's a notebook of events, thoughts and ideas for use by my future self. As well as the occasional random person coming through here via the search engines looking for some obscure piece of data, like the SNMP MIBs required to dump a routing table from a Riverstone.

Sunday, January 21, 2007

Africa USA fifty-four years later

This afternoon, Spring sprung a surprise straggle—why not visit Africa USA? Or rather, what's left of Africa USA.

It was fairly easy to find and get to, despite it appearing like a gated community (there were, in fact, no closed gates, and the gate house itself was devoid of anything). The only structure left from the park is a bridge, leading to an overgrown patch of land with a decaying asphalt walkway. The bridge to Monkey Island has long since fallen apart.

Fortunately for us, no velociraptors were left when the park closed.

[Africa USA—now Camino Gardens]
[Although it's not very well guarded for a gated community]
[It is surrounded by Soviet style apartment buildings]
[Making it a kind of “Soviet Bloc” if you will]
[Welcome to all that's left of Africa USA]
[Nice, but it's still a private park]
[About the only structure remaining from Africa USA]
[“Head on through to the other side”]
[Looking back at civilization]
[Reminds me of Poca Boca in a way]
[The bridge to Monkey Island is no longer around]
[although with the water level like this, you might not need a bridge to get to Monkey Island]
[Signs of civilization are nearby though]
[Some very impressive Royal Palms]
[The end of the path]
[The end of the path at Africa USA leads to the Soviet Bloc]
[Some of the vegetation overgrowth at Africa USA]
[More overgrowth of vegetation]

Monday, January 22, 2007

Yes, I can say “intellectualizing things into the ground.”

You think that's bad? Just look at how my joke about Leni Riefenstahl and Snuggles the Bear has spawned this mega-crossposted thread about the differences between fascism and absolute monarchy.

Can you say, “intellectualizing things into the ground?”

Douglas Lathrop

Via Eric Burns is Visited States Page, where you can get a map highlighting the states you've visited.

[States I've visited, although “wierd” wasn't listed]

The red states represent the ones I've “visited” although I use that term very loosely.

For instance, while I have Texas highlighted, I've only seen the state while sitting in the Dallas-Ft. Worth airport, so to say I “visited” the state is a bit of stretch. Yes, technically I was in Texas, I was looking at plastic seats in an air conditioned terminal that could have been anywhere to tell the truth.

Arizona is also highlighted, but again, it's a technicality—albeit with a better claim of “visited” than Texas. Hoade and I actually saw the state when we parked our car on the Arizona side of Hoover Dam, but it wasn't much different looking than Nevada, and we only really ventured maybe a quarter mile into the state.

I can say with better conviction that I've “vistied” Wisconsin, but that was in Milwaukee, and even then, downtown Milwaukee at the Convention Center (and a few blocks west to the hotel). Actually, I feel better about saying I “visited” Milwaukee than I do about “visiting” Wisconsin. The same about New York—It was New York City I “visited,” not the state at large. Pennsylvania wasn't much better. Sure, I flew into the city, but I actually stayed in New Jersey.

Tennessee, Kentucky and Ohio only get mention because they were “drive through” states—back when I lived in North Carolina, my Grandma would drive down from Michigan to pick me up for the summer vacation. The route followed I-75 through those states.

Maryland was a “sail through” state—one summer I spent with my Dad sailing along the Chesapeake Bay, so was I really in Maryland, or just alongside it?

Really, about the only state I can say that I've “visited” is Florida (and yes, I live here). I've been along both the east and west coast, central and north Florida, and out through the panhandle.

The only other state I've seen significant portions of is North Carolina, and I've yet to actually see the central portion (having lived in both the mountainous western portion, and the coastal eastern portion).

Then again, I'm probably over intellectualizing a silly web meme.


You can't make this stuff up

Yes, the UFCW is outsourcing its picketing to non-union workers, at a sub-standard pay rate with no benefits, in unsafe conditions, with no transportation or means to leave the premises, in order to protest the poor jobs inside Wal★Mart, where workers make twice as much.

Via Right on the Left Coast, The. Best. Union. Story. Ever.

Wlofie and I have had several discussions about unions, how they work here and in Sweden, and I feel he feels that our unions are all smoking crack.

Yes, I would have to agree with him.

Tuesday, January 23, 2007

An even longer entry to scare away the new readers

Now, about that article … (hold on, it's a long one)

I'm talking about the limitations of programming which force the programmer to think like the computer rather than having the computer think more like the programmer. These are serious, deeply-ingrained limitations which will take a lot of effort to overcome. I'm not being pretentious when I say that this will be the next big paradigm shift in programming. We will need to completely redefine the way we write programs.

In this article, I present my view and my current work toward Language Oriented Programming (LOP). First I will show what is wrong with mainstream programming today, then I'll explain the concept of LOP by using the example of my existing implementation, the Meta Programming System (MPS). This article is intended to give you a bird's-eye-view of LOP, to spark interest in the idea, and hopefully to generate feedback and discussion.

Language Oriented Programming: The Next Programming Paradigm

The concept of using the best language suited to the problem at hand dates back to the first computer language devises, Fortran. The very name, Fortran, stands for “Formula Translation” and was a way to express mathematical equations in the more natural notation of

xn1 = ((A * yn) + B) * xn * (1.0 - xn)
yn1 = ((C * xn) + D) * yn * (1.0 - yn)

and have the computer take the work of translating that to

	fld	[A]
	fmul	[yn]
	fadd	[B]
	fmul	[xn]
	fld	[xn]
	fld1
	fsub
	fmul
	fst	[xn1]

	fld	[C]
	fmul	[xn]
	fadd	[D]
	fmul	[yn]
	fld	[yn]
	fld1
	fsub
	fmul
	fst	[yn1]

(the sample above assumes the instruction set supports floating point—if it doesn't, then you have a lot more code to call subroutines to do the work of adding, subtracting and multiplying floating point numbers; it's not pretty)

And even if a single language doesn't perfectly handle the entire problem domain, it has been possible for quite some time to do multilanague compilations, depending up platform. The most common method is to embed some routines written in Assembly to speed things up (since everything is converted to Assembly eventually), but as long as an operating system defines a standardized way to pass data between routines, it's not that hard to mix-n match routines from multiple languages.

I'm looking at the technical information for OS-9 (not to be confused with Mac OS 9), specifically for software modules:

A module need not be a complete program or even 6809 machine language. It may contain BASIC09 “I-code,” constants, single subroutines, and subroutine packages.

The module header contains a value specifying the language type, with values defined for data only, 6809 machine code, BASIC09-I-code, Pascal I-code and COBOL I-code. In theory then, you can construct, say, a pay roll system using a Fortran compiler to generate the math routines into 6809 code, COBOL to generate the business rules, and allow extentions to be written in BASIC. The language type is probably there for two reasons; 1) to know how to run the module, and 2) to figure out what parameter passing conventions to use (if there are any differences between the languages).

AmigaOS has a similar feature—you can create external libraries in any language you care to (say, in Pascal) and call them in programs written in any other language (say, in C—since the operating system itself is a library, any compiler on the Amiga had to support the paramter passing convention used in the system libraries, and while the only compiler I used on the Amiga was a C compiler, it had extentions to make external libraries, so I assume other compilers would have the same).

Even Microsoft Windows and IBM's OS/2 had a similar feature—DLLs. And from what I understand, it's not uncommon to have a “program” using DLLs written in C, C++ and Visual Basic at the same time.

But what Sergey Dmitriev is talking about is not multi-language programs per se but developing a domain specific languages to solve the problem. Or multiple domain specific languages if that's required.

And I have problems not only with that concept, but with his particular way of doing that as well. And no, it's not having to learn a million tiny computer languages (that's actually expected in this industry—when I started, the first language taught at FAU was Fortran, and while I was there, I saw the switch to Pascal and then C; after I left, it went to C++ and then Java).

That's not to say I have anything against DSLs—I think they're great, and I've written one or two in my time. When I worked at FAU, I ended up writing a DSL to generate programs to run Miller's Analogies (I worked as a programmer in the Math Department for a professor of Psychology—no, I don't fully understand how or why a psychologist ended up in the math department) which looked like:

mat 'CROWN' isto 'ROYAL' as
        'prayer'
        'crucifix'
        'priesthood'
        'bible'         [sel]
isto 'RELIGIOUS'
'b'     answer

mat 'SMALL' isto 
        'tiny'
        'petite'
        'little'
        'diminutive'    [sel]
as 'LARGE' isto 'BIG'
'c' answer

mat 'WORM' isto 'BIRD' as 'MOUSE' isto
        'man'
        'snake'
        'rodent'
        'lion'          [sel]
'b' answer

mat
        'artist'
        'description'
        'narration'
        'personality'   [sel]
isto 'CHARACTERIZATION' as 'PICTURE' isto 'PORTRAIT'
'b' answer

mat
        'orate'
        'sing'
        'mumble'
        'speak'         [sel]
isto 'TALK' as 'SCRAWL' isto 'WRITE'
'c' answer

But there was one problem with this, and it's one of the problems I have with DSLs—the time it took me to write the DSL, which generated C code to handle the Miller's Analogies exceeded the time it would have taken me to write the C code initially! How much time? It took me maybe a month or so to write the DSL to the point where it would generate the necessary C code, maybe longer—it's been over ten years.

Now, I was lucky in that my job wasn't exactly fast paced, and I had the luxury of playing around with language design even though that wasn't my job. But as it was, I only did the one program with Miller's Analogies and from a purely economical standpoint, the work I did was wasteful (educational wise, it wasn't, as I was able to later use the work I did for the DSL as part of a class project, but sometimes it can be hard to justify research work in a non-research environment). So basically, unless the time it takes to write the DSL and the solution in said DSL is smaller than the time it would take to write the solution in a pre-existing language, or the DSL can be used more than once, it's not economically viable.

The other problem I have with DSL—what if you have the wrong mental model of the problem?

Going back to my hypothetical SNMP language extentions. The code as I wrote it looked like (bug fixed in this version):

IPAddress destination[];
IPAddress mask[];
IPAddress nexthop[];
int       protocol[];
int       age[];
int       metric[];
int       type[];
OID       sys = SNMPv2-MIB::sysObjectID.0;

if (sys == SNMPv2-SMI::enterprises.5567.1.1)	/* riverstone */
{
  destination = IP-MIB::ip.24.4.1.1;
  mask        = IP-MIB::ip.24.4.1.2;
  nexthop     = IP-MIB::ip.24.4.1.4;
  protocol    = IP-MIB::ip.24.4.1.7;
  age         = IP-MIB::ip.24.4.1.8;
  metric      = IP-MIB::ip.24.4.1.11;
  type        = IP-MIB::ip.24.4.1.6;
}
else if (sys == SNMPv2-SMI::enterprises.9.1)	/* cisco */
{
  destination = RFC1213-MIB::ipRouteDest;
  mask        = RFC1213-MIB::ipRouteMask;
  nexthop     = RFC1213-MIB::ipRouteNextHop;
  protocol    = RFC1213-MIB::ipRouteProto;
  age         = RFC1213-MIB::ipRouteAge;
  metric      = RFC1213-MIB::ipRouteMetric1;
  type        = RFC1213-MIB::ipRouteType;
}

/* skip the printing part */

Nice. Concise. And totally wrong!

Well, not totally—it'll work as is, but it does have a major problem, and it stems from my not fully understanding the SNMP protocol (ah, gotta love those leaky abstractions). SNMP is a network protocol, and each request for data via SNMP requires a round trip across the network. That's fine for single values, like the request for SNMPv2-MIB::sysObjectID.0. But the MIB RFC1213-MIB::ipRouteDest is a “table” (an “array” in SNMP-speak) and each element requires a request (it's a bit more complicated than that, but it's not germane to this discussion). The code above is basically doing the following (and I'll only follow the Cisco branch since it's a lot of code here):

for (
      i = 0 , mib = RFC1213-MIB::ipRouteDest;
      mib != NULL ; 
      destination[i++] = mib.result
    )
{
  send(mib);	/* send the requst */
  /*--------------------------------------------------
  ; due to the nature of SNMP tables, you get back
  ; not only the value of the MIB you asked for, but
  ; the MIB of the next entry in the table.
  ;
  ; Hey, I didn't write SNMP
  ;-------------------------------------------------*/

  mib = receive();
}

for (
      i = 0 , mib = RFC1213-MIB::ipRouteMask;
      mib != NULL;
      mask[i++] = mib.result
    )
{
  send(mib);
  mib = receive();
}

for (
      i = 0 , mib = RFC1213-MIB::ipRouteNextHop;
      mib != NULL;
      nexthop[i++] = mib.result
    )
{
  send(mib);
  mib = receive();
}

for (
      i = 0 , mib = RFC1213-MIB::ipRouteProto;
      mib != NULL;
      protocol[i++] = mib.result
    )
{
  send(mib);
  mib = receive();
}

for (
      i = 0 , mib = RFC1213-MIB::ipRouteAge;
      mib != NULL;
      age[i++] = mib.result
    )
{
  send(mib);
  mib = receive();
}

for (
      i = 0 , mib = RFC1213-MIB::ipRouteMetric1;
      mib != NULL;
      metric[i++] = mib.result
    )
{
  send(mib);
  mib = receive();
}

for (
      i = 0 , mib = RFC1213-MIB::ipRouteType;
      mib != NULL;
      metric[i++] = mib.result
    )
{
  send(mib);
  mib = receive();
}

But the original code in ospfquery is doing the following:

mib.dest     = RFC1213-MIB::ipRouteDest;
mib.mask     = RFC1213-MIB::ipRouteMask;
mib.nexthop  = RFC1213-MIB::ipRouteNextHop;
mib.protocol = RFC1213-MIB::ipRouteProtocol;
mib.age      = RFC1213-MIB::ipRouteAge;
mib.metric   = RFC1213-MIB::ipRouteMetric1;
mib.type     = RFC1213-MIB::ipRouteType;
i            = 0;

while(mib.dest)
{
  send(			/* yes, all this is sent */
	mib.dest,	/* in one packet */
	mib.mask,
	mib.nexthop,
	mib.protocol,
	mib.age,
	mib.metric,
	mib.type
  );
  
  mib.dest,		/* and received in one packet */
  mib.mask,
  mib.nexthop,
  mib.protocol,
  mib.age,
  mib.metric,
  mib.type = receive();

  destination[i] = mib.dest.result;
  mask[i]        = mib.mask.result;
  nexthop[i]     = mib.nexthop.result;
  protocol[i]    = mib.protocol.result;
  age[i]         = mib.protocol.result;
  metric[i]      = mib.metric.result;
  type[i]        = mib.type.result;
  i++;
}

Now, I should mention that send() causes a single SNMP packet to be sent, and receive() receives a single SNMP packet. With that, you can now see that the code as I envisioned it sends a metric buttload of traffic compared to the code as ospfquery implements (about seven times the traffic). The other major difference is that my code requires all the data to be collected before it can be printed, whereas the code in ospfquery can print the results as it gets them (not that it does currently, but it can). So even if the two methods take the same amount of time, the second one seem faster (it's the perception that it's faster that is important in this case).

The distinction is subtle, and on our routers it's mostly academic, what with their two dozen or so routes. But I actually ran ospfquery on the core router, with its 78,500 routes, and the difference is no longer academic (ospfquery does not print routes until it collects all the data, and at first, I thought the program might have crashed; nope, it just took a while).

And the problem stems from my misunderstanding of the problem, and my proposed DSL, while it works, is sub-optimal and in fact, may cause problems as it scales (in this particular case).

I've also seen what happens to code over time as multiple people maintain the code. I shudder to think what would happen to a language over time as multiple people maintain it (hmmm … that might help explain Perl—I'll have to think on this).

Now, getting back to Mr. Dmitiev's article:

When a compiler compiles source code, it parses the text into a tree-like graph structure called an abstract syntax tree. Programmers do essentially the same operation mentally when they read source code. We still have to think about the tree-like structure of the program. That's why we have brackets and braces and parentheses. It's also why we need to format and indent code and follow coding conventions, so that it is easier to read the source.

Why do we resort to text storage? Because currently, the most convenient and universal way to read and edit programs is with a text editor. But we pay a price because text representations of programs have big drawbacks, the most important of which is that text-based programming languages are very difficult to extend. If programs are stored as text, you need an unambiguous grammar to parse the program. As features are added to the language, it becomes increasingly difficult to add new extensions without making the language ambiguous. We would need to invent more types of brackets, operators, keywords, rules of ordering, nesting, etc. Language designers spend enormous amounts of time thinking about text syntax and trying to find new ways to extend it.

If we are going to make creating languages easy, we need to separate the representation and storage of the program from the program itself. We should store programs directly as a structured graph, since this allows us to make any extensions we like to the language. Sometimes, we wouldn't even need to consider text storage at all. A good example of this today is an Excel spreadsheet. Ninety-nine percent of people don't need to deal with the stored format at all, and there are always import and export features when the issue comes up. The only real reason we use text today is because we don't have any better editors than text editors. But we can change this.

Language Oriented Programming: The Next Programming Paradigm

A laudable idea, but not quite so simple as Mr. Dmitriev makes it out to be. Sure, the example I gave before:

xn1 = ((A * yn) + B) * xn * (1.0 - xn)
yn1 = ((C * xn) + D) * yn * (1.0 - yn)

Can be made easily into a graph:

[graph of “xn1 = ((A * yn) + B) * xn * (1.0 - xn)”]

(Okay, so it's a graph of just the first statement)

I even color coded it—red for modified variables, green for variable references, blue for constants, and black for operations. But what about the following bit of code for a Connecton Machine?

(DEFUN PATH-LENGTH (A B G)
  α(SETF (LABEL •G) +INF)		; step 1
   (SETF (LABEL A) 0)			; step 2
   (LOOP UNTIL (< (LABEL B) +INF)	; step 3
         DO α(SETF (LABEL •(REMOVE A G))
                   (1+ (βMIN α(LABEL •(NEIGHBORS •G))))))
   (LABEL B))				; step 4

This algorithm, which finds the length of the shortest path between A and B in graph G is as follows:

  1. Label all vertices with +∞.
  2. Label vertex A with 0.
  3. Label every vertex, except A, with 1 plus the minimum of its neighbor's labels. Repeat this step until the label of vertex B is finite.
  4. Terminate. The label of B is the answer.

The notation is a bit weird I admit, but basically, “α” is similar to Common Lisp's MAPCAR, which maps a function to each element of a list, so the first line could be translated as:

(MAPCAR #'(LAMBDA (V) (SETF (LABEL V) +INF)) G)

The “•” is what we're mapping over, and “β” is a reduce operation—it maps a function over each element of a function; this function accumulates a single value result. For instance:

(REDUCE #'+ 0 '(3 7 2 99 4 3))

will add all the elements in a list and return a sum, whereas:

(REDUCE #'MAX 0 '(3 7 2 99 4 3))

will return the smallest value in a list. “α,” “β” and “•” aren't actually MAPCAR, REDUCE and the target we're iterating over, but it's close enough.

Now, getting back to my argument here. Again, the code itself is pretty easy to turn into a tree (it already is in tree format, but it's hard to see the tree for all the parenthesis) but still, what does that give us? While I think the Connection Machine notation is elegant, C doesn't exactly have the concept of MAPCAR & Co. It can be faked, sure, but it's not an inherent part of the language.

But what it seems Mr. Dmitriev is working on is a type of automated template system, where you define your extensions, then create a templated implementation for your target language, only using a specialized editor. You do this for everything—from simple operations and assignments up through function calls and modules. And you need to define the ways these things all interact (hopefully to avoid some of the darker corners of C++, for instance).

Seems like quite a bit work, even if Mr. Dmitriev states a lot of this is automagically generated (and that's scary in and of itself—automagically generated stuff; I tend to distrust automagically generated stuff unless I understand exactly what's going on).

And from the looks of Mr. Dmitriev's editor (in his system, you don't manipulate textual source code, which is primitive stone age programming) it appears to target Java; I wonder how it would fare in trying to extend C with Lisp like features? Or Lisp with Forth like features? Or even C with my propsed SNMP like features?

Oh, and the reason we still use text to store source code? Because I can still load 40 year old source code into my text editor and modify it. What happens 40 years down the line with code written in Mr. Dmitriev's editor?


Just because.

I guess the part I don't understand is the target audience. Who is so serious about writing that they need a full-screen editor, but so unserious that they don't have a favorite editor already? I've published two full- length books and posted a hell of a lot more than that, and you can pry my text editor from my cold dead hands. I'm not even going to mention which one it is; it doesn't matter. Switching to a new one would be a frustrating and painful experience that would get in the way of my writing for weeks, maybe months.

Via decafbad.com, Mark Pilgrim: wrongroom

It could also be “because I can.”

Or because the software being used sucks and it's easier to start over than try to work on an existing project.

Any number of reasons.

But I can certainly relate to the trauma of switching editors. Heck, it was traumatic switching email clients and I'm still finding flaws in mutt (just last night, I patched it to change the default location for saving attachments, since I hate cluttering up my home directory).

Wednesday, January 24, 2007

The Good Shepard

The Good Shepard” is about Edward Wilson (played by Matt Damon) and the founding of the CIA. The movie starts with The Bay of Pigs and Wilson's involvement in it. Then through a series of flashbacks we follow the life of Wilson as he attends Yale, is picked for OSS during World War II and later as it evolves into the CIA.

It's a good film, and rather understated for a major Hollywood production, and it didn't feel like the three hour film that it was (a good sign). There are good performances from everybody in the film, but a problem I had was with Matt Damon. While he's good as Edward Wilson, I found it very hard to accept him as middle aged with a son in college (during the Bay of Pigs incident, around which the movie plot revolves). I just found him too young looking to be the middle age secret service beaurocrat—even Angelina Jolie as his wife manged to “age” more believably than Matt Damon.

But that's really my only gripe with this otherwise good film.

Thursday, January 25, 2007

That's not what I wanted, Firefox

That was odd.

I'm working remotely, using a Linux desktop system, and I'm trying to log into the trouble ticket system at The Office. It's a web-based trouble ticket system, so I'm using Firefox as my browser of choice. Now, because I haven't logged into the trouble ticket system from where I'm currently am, it's not bookmarked or in my browser history.

“No problem,” I say to myself. “I'm using X Windows, and since my workstation at The Office also uses X Windows, I can run Firefox on my workstation and have it displayed on the computer I'm currently using.” I mean, that's the whole purpose of X—you can run applications on one computer and have its windows displayed elsewhere. This is so fundamental to X that its been a feature since the late 80s (pcAnywhere is a Johnny-come-lately to remote GUI software).

So I log into my workstation and run Firefox. Yes, there is a lag before the window pops up, but I'm expecting that—I am running a graphical program across the Internet. But the window … it looks … wrong. I mean, it is Firefox, but the window isn't big, and the bookmarks aren't the ones I expect.

In fact, it looks much like the bookmarks on the copy of Firefox I'm running locally. And in fact, the browser history doesn't show the trouble ticket system.

In fact, the Firefox on my workstation at The Office apparently sent a command message to the Firefox on the computer in front of me to open up a new window.

Which, while pretty cool in a “network optimization” way, is not what I was expecting. To get around this mess, I had to shut down the local Firefox before firing up Firefox at The Office.

I know of no other X program that exhibits this behavior. xeyes? It'll run remote and locally. xterm? It'll run remote and locally. Gimp? It'll run remote and locally. Firefox? It apparently goes out of its way to run in only one location—must be a vestige function left over when it was the commercial product Netscape.

There is a way around it though:

It seems the switch you are looking for is -no-remote. And yes, it does not appear with you run firefox -h, because firefox -h gives you the sitches supported by the program firefox.

What's this -no-remote then, you say? Well that switch is implemented by the wrapper script. Pish tosh, a wrapper script is some silly linux distribution script, you would think. But look at the license and the copyright and you'll find this is part of the standard firefox distribution. The method for getting the wrapper script appears to be to open it in vi. At least, that's the method I used. My firefox manpage does mention it too, but that's hardly an excuse.

spc hates software: Okay Firefox, that's … interesting. Now cut it out!

Oddly enough, the man page I have on my workstation at The Office fails to mention -no-remote, and the man page on the computer I'm using fails to mention -no-remote—they do, however, mention - remote, but that appears to be redundant, since that appears to be the default action anyway.

Sigh.


I, for one, welcome our new computer based overlords

I spoke recently with an old friend who is a bandwidth broker. He buys and sells bandwidth on fiber-optic networks around the world. And he told me something that I found not completely surprising, but I certainly hadn't known: Google controls more network fiber than any other organization. This is not to say that Google owns all that fiber, just that they control it through agreements with network operators. I find two very interesting aspects to this story: 1) that Google has acquired—or even needs to acquire—so much bandwidth, and; 2) that they don't own it, since probably the cheapest way to pick up that volume of fiber would be to simply buy out any number of backbone providers like Level 3 Communications.

Wh en Being a Verb is Not Enough: Google wants to be YOUR Internet.

A long staple of science fiction is the sentient computer. From When Harlie was One and The Adolescence of P-1 to The Forbin Project, we've had computers becoming aware and then possibly trying to take over the world (or the moon, in the case of The Moon is a Harsh Mistress) but in all these cases, it was a single computer gaining self-awareness; never was it a cluster of machines (well, maybe the Borg but those aren't exactly computers we're talking about).

But Google?

Google has thousands of computers, all networked. Each computer is simple, but then again, so is a single neuron. But all those simple computers are connected together, again, like neurons. And I think that our conscienceness arises from the pattern of said connections; that you get emergent behavior from billions of such simple connections. And while Google is far from having billions of connections, it certainly has more connections than just about anything else. Unlike, say, my site, where you can point to a single computer (currently in Miami) and say “that's Conman Laboratories,” you just can't point to a single computer and say “that's Google,” much like you can't point to a single skin cell and say “that's Sean Conner.”

Google is more than the sum of its parts.

And if any computer, or cluster of computers, will exhibit emergent behavior, it will be Google (or more technically, the Google cluster).

I'm wondering if that hasn't already happened to some degree.

Or maybe, just maybe, Google is Skynet

Friday, January 26, 2007

No, I haven't forgotten about it

But I have been neglecting it for the past few months. Partly due to the Holiday Season, and partly because I was (or did) run out of ideas to write about at the Saltmine Chronicles.

And all this is just to inform those that are interested that I just posted—an entry about good and bad web traffic.


A leaky domain specific language

Continuing on about that article, there's yet another reason to be wary of DSLs: The Law of Leaky Abstractions (which itself is an extension of the wrong mental model, to a degree).

Going back to my hypothetical SNMP extensions:

IPAddress destination[];
IPAddress mask[];
IPAddress nexthop[];
int       protocol[];
int       age[];
int       metric[];
int       type[];
OID       sys = SNMPv2-MIB::sysObjectID.0;

if (sys == SNMPv2-SMI::enterprises.5567.1.1)	/* riverstone */
{
  destination = IP-MIB::ip.24.4.1.1;
  mask        = IP-MIB::ip.24.4.1.2;
  nexthop     = IP-MIB::ip.24.4.1.4;
  protocol    = IP-MIB::ip.24.4.1.7;
  age         = IP-MIB::ip.24.4.1.8;
  metric      = IP-MIB::ip.24.4.1.11;
  type        = IP-MIB::ip.24.4.1.6;
}
else if (sys == SNMPv2-SMI::enterprises.9.1)	/* cisco */
{
  destination = RFC1213-MIB::ipRouteDest;
  mask        = RFC1213-MIB::ipRouteMask;
  nexthop     = RFC1213-MIB::ipRouteNextHop;
  protocol    = RFC1213-MIB::ipRouteProto;
  age         = RFC1213-MIB::ipRouteAge;
  metric      = RFC1213-MIB::ipRouteMetric1;
  type        = RFC1213-MIB::ipRouteType;
}

/* skip the printing part */

This time, I'll be concentrating on just querying one SNMP variable:

OID sys = SNMPv2-MIB::sysObjectID.0;

if (sys == SNMPv2-SMI::enterprises.5567.1.1)
  printf("Riverstone\n");
else if (sys == SNMPv2-SMI::enterprises.9.1)
  printf("Cisco\n");
else
  printf("Unknown\n");

I thought it would be instructive to write the minimum amount of code that actually does this, using the net-snmp library. And yes, it was instructive.

/********************************************
* to compile, install net-snmp, then
*
* gcc -o sysid sysid.c -lsnmp -lcrypto
*
*********************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#include <net-snmp/net-snmp-config.h>
#include <net-snmp/utilities.h>
#include <net-snmp/net-snmp-includes.h>

/*************************************************************************/

int main(int argc,char *argv[])
{
  static oid       sysObjectId[] = { 1,3,6,1,2,1,1,2,0};
  static oid       rs[]          = { 1,3,6,1,4,1,5567 };
  static oid       cisco[]       = { 1,3,6,1,4,1,9 };
  netsnmp_session  session;
  netsnmp_session *ss;
  netsnmp_pdu     *pdu;
  netsnmp_pdu     *response;
  int             status;

  snmp_parse_args(argc,argv,&session,"",NULL);

  ss = snmp_open(&session);
  if (ss == NULL) exit(1);

  pdu = snmp_pdu_create(SNMP_MSG_GET);
  snmp_add_null_var(pdu,sysObjectId,9);
  status = snmp_synch_response(ss,pdu,&response);
  
  if ((status == STAT_SUCCESS) && (response->errstat == SNMP_ERR_NOERROR))
  {
    if (memcmp(response->variables->val.objid,rs,sizeof(rs)) == 0)
      printf("Riverstone\n");
    else if (memcmp(response->variables->val.objid,cisco,sizeof(cisco)) == 0)
      printf("Cisco\n");
    else
      printf("Unknown\n");
  }

  snmp_free_pdu(response);
  snmp_close(ss);
  return(EXIT_SUCCESS);
}

So, where are the leaks?

Well, there's creating the actual session, or some other way of specifying which router we're attempting to query and the credientials we need to actually obtain the information (and there are three versions of the SNMP protocol, so we need to specify that as well somewhere). In my code, that's hidden behind the call to snmp_parse_args(), which expects to parse the command line and creates a template “session” for us (and believe me, I tried to see if there was any other way to construct this template “session” and I couldn't find it in the hour or so I looked). This is leak number one.

Then there's the actual call itself. You create the message, fill it with the variable(s) you want, then send the query and get a response back. But, there are several things that can go wrong, which is leak number two.

The first thing is that we never get a response back—the SNMP library simply times out (is the router down? A bad network cable? Who knows?). That's reflected in the return code from snmp_synch_response(). But even if we get a response back, the far side, the device we're querying via SNMP, can return an error—perhaps it doesn't support the MIB we requesting. Or the response itself got corrupted on the way back. And this is still part of leak number two.

The primary line I'm trying to implement:

OID sys = SNMPv2-MIB::sysObjectID.0;

So far, there are three things (at least, possibly more) that could go wrong: I never get a reponse back, the response I get back is an error, or I get the actual data I requested. What now?

Well, my hypothetical langauge extension could just set sys to NULL, indicating an error, but what error? Well, I could just stuff something into errno (if I'm extending C, for example):

string contact  = SNMPv2-MIB::sysContact.0;
string name     = SNMPv2-MIB::sysName.0;
string location = SNMPv2-MIB::sysLocation.0;

if ((contact == NULL) || (name == NULL) || (location == NULL))
{
  if (errno == ETIMEOUT)	/* timeout */
    ...
  else if (errno == EMIBEXIST)	/* MIB not supported */
    ...
  else
    ...
}

But that's error detection, and that's a whole other ball of mud.

And setting aside I still haven't specified which device I'm querying, this has another leak—I should bundle these three queries into a single SNMP query for better (faster, less bandwidth intensive) performance. I suppose the “compiler” could recognize this and do the bundling for us, but that's some sophisticated programming for just a seemingly simple DSL.

Saturday, January 27, 2007

A safari in our own back yard

So while Africa USA might be gone, there's still Lion Country Safari, but unlike Africa USA, where you ride around the park in a train, in Lion Country Safari you drive your own car through the park, gazing at the various animals. And for the most part, they roam around free, except for the lions and giraffes, which are fenced off and the elephants and monkeys, which are kept behind moats.

At the end of the drive, there's a small theme park in place, I guess to keep the kids occupied in case seeing wild animals wasn't enough. And like most theme parks, the food and drinks are vastly overpriced, the gift shop is overly-hawked, and the kids whine to their parents to buy said overpriced food, drink and trinkets.

[This guy just wouldn't get out of the way] [On the lookout for predators] [That's one large chicken there] [Animals where just everywhere] [For some reason they keep the cats locked up] [Maybe to keep the cats from eating these] [A water buffalo enjoying the water] [Those are some large horns.  Wonder if he's compensating for anything?] [The obligatory African elephant] [More deer-like animals] [Considering their poor eyesight and large weight, yeah, I can see rhinos having the right of way] [What you don't see is a rhino trying to hump a Volkwagen Beetle—it was most amusing] [Looks like some horses escaped from a nearby jail] [And we can't have a theme park in Florida without pink Flamingos, can we?] [Obligatory giraffes] [Now this guy … not only did he keep saying “Hello” and ”Goodbye” but he took a fancy to me and kept trying to hog the camera.] [This guy, however, gave me the cold shoulder] [The parrots are real, however the girl was animatronic.] [I think they've confused alligators, which are found in our backyard, with crocodiles, which are found in Africa] [Still, I don't think I want to argue the point with him] [No comment.]

Sunday, January 28, 2007

A little bit of urban exploration

There's a building under contruction along I-95 just south of Lantana Blvd. that Spring was interested in checking out, although it's still under construction and access to the site is rather restricted.

[The building in question]

In order to get around this restriction, we felt it would be easier to walk along the traintracks and approach the site from the east. Once the Tri-Rail trains passed, we proceeded south along the tracks.

[Heading south along the tracks]

Unfortunately, the vegetation along between the tracks and the building in question was too thick to tromp through, and we neglected to bring any form of machette with which to forge a trail. And the one trail we did find had evidence of a homeless homestead and not wanting to provoke any confrontation, we left the area.

We never did learn what the building was being built for.

Monday, January 29, 2007

Thinking with the aliens

My language is not about designing words or even visual symbols for people to interpret. It is about being in a constant conversation with every aspect of my environment, reacting physically to all parts of my surroundings.

Via kisrael, In My Language

It's a video, but you might want to skip to 03:12 where she stops “talking” in her language and offers a translation, or more loosely, an explanation of what she it communicating, which isn't really meant for human consumption.

What makes this interesting to me (at least, the part after the first 3′15″ of her video) is her definition of “language” and “communication.” And since it's not intended for human interaction, it reminds me very much of the concept of varelse, although it's clear she isn't strictly varelse, but possibly ramen (more information). It also reminded me of Dr. Temple Grandin, who has the uncanny ability to think like a cow and can thus, communicate for them to us (and both women suffer from Autism, although to varying degrees).

I write about stuff from the perspective of an autistic person, because that's part of what I am (I'm also a lot of other things, including probably brain damaged). But when I write about the experience of not being a “person” until I learn a foreign language, I'm not writing to give insight into autism specifically. I'm writing because that's true even in accepted languages, that people are more “people” when they speak the dominant language, or the dominant dialect. I'm writing because that's true of people with brain damage, people with Alzheimer's, people with intellectual disabilities, people whose bodies don't let them form speech easily even if their cognition is totally standard, people considered crazy (in all the various ultra-sophisticated medicalizations of that basic concept), etc, and I see it all the time.

This stuff isn't just about autism.

There's also a lot of food for thought in this MetaFilter thread.

Tuesday, January 30, 2007

I thought people worked during the day

I have a few checks to deposit while the bank is still open, I figured, as long as I'm out, I might as well do the grocery shopping. Normally, I would do this around 6:00 pm, but this week's shopping list isn't long, and it would keep the day from being broken up.

And I'm frankly amazed at how crowded Costco is for mid-afternoon on Tuesday. Don't these people have jobs to go to? Normally, I get to park near the store, but today I'm way out in Farlotistan and have to trudge the half mile to the store. Usually the front of the store is crammed full of shopping carts—today, I have to return to Fatlotistan to retreive a cart.

They also seem to have plenty of food tasting stations throughout the store. At the end of every isle is another hot plate stand, manned by a person cooking some type of food-like item. Everything from Burbon Chicken to brownies. And every one of these food tasting stations is blocking half the isle, making it difficult to maneuver through the already crowded store.

So I'm torn. I like the idea of getting the grocery shopping over with while the sun is still up, thus leaving me with larger blocks of time to work. But the store isn't as crowded later in the evening. So, I have to ask myself: is going shopping during the daytime worth the crowds?


Gives a whole new meaning to “bit bucket”

Today it's a chilly 11 degrees outside and, coincidentally, our office Internet connection has been going up and down. The woman walks by me and leans over and tells me that “our Internet connection is bad today because the tubes probably have ice in them.”

It's a Series of Tubes

Nothing much else to add, except for “read the whole thing.”

Wednesday, January 31, 2007

National Gorilla Suit Day

[Have a Happy National Gorilla Suit Day Today!]

Even though there's no line, there's still a line

All I needed was a single 39¢ stamp.

So on the way to work, I decided to stop by the Post Office because I know they have a machine that sells single 39¢ stamps.

Only the machine is out of order.

Sigh.

I check over in the customer area and amazingly enough there is no line! Suspicious that it might be another holiday I approach, and lo', it's not a holiday! And there are two customers already being helped.

This should only take a minute or two, I think to myself as I get into the non-existant line.

The customer at the far end is talking to the clerk, who makes a dash back into the bowels of the Post Office, only to come back, talk some more with the customer, and dash back into the bowels.

The customer closer to me is patiently waiting while the clerk applies special postal tape to the package, then afixes labels to the package, then fills out said labels, then stamps a whole mess of official looking documents, afixes yet more tape and labels while filling out even more official looking paper work.

Meanwhile, the far customer is still talking to the clerk, who keeps dashing back into the bowels of the Post Office.

A line starts to form behind me. The clerk nearest me finishes wrapping a cacoon around the package, and then I see the customer has two more packages.

So much for it taking a minute, I think, about five minutes later.

Ten minutes after I started waiting, the far customer finally berates the clerk over some small detail, then leaves. Now I can finally buy the single 39¢ stamp.


My alarm clock sounded suspiciously like a phone

Ring.

Ring.

Ring.

“Mughuwaha?”

“Sean,” said Smirk. “You awake?”

“Mughuawhaha,” I said.

“Our customer S is complaining about network lag, what's the address of their installation of Cacti?” I gave Smirk the address, and he was able to log in. “Thanks.”

I fall back asleep again.

Ring.

Ring.

Ring.

“Hugmugahwah?”

“Sean!” It was Smirk yet again. “Somethings wrong with their installation of Cacti—there's no data for the past two weeks.” Oh great, I thought. “Can you look into it?”

“Yeah,” I said, resigning myself to the fact that yes, I am getting up early today.


Notes on IPTables

The problem this morning was a direct cause of my inability to fully grok iptables. I logged into the customer's firewall (we offer managed firewalls as one of our services), which was also running an instance of Cacti to help monitor their network. Sure enough, the SNMP polling script was failing for some obscure PHP reason.

Poking around the system, I found a few suspicious files, time stamped two weeks ago, named ping, ping.1 and ping.txt. Odd, I thought and when I checked the contents, yup—a script kiddie script, which opens up a connection to a remote computer.

Sigh.

More poking around, and I find rather quickly the IRC bot program the script kiddie was running (all files owned by the webserver).

Okay. Cacti has some … issues … with security, and it's no surprise that the script kiddie … exploited … these issues, to install their nefarious wares. And the network latency the customer was experiencing was due to excessive IRC traffic.

The major problem I had was how the script kiddie got access to the webserver in the first place. Due to Cacti's … issues … with security, I had explicitly blocked access to all network services with iptables (with the exception of traffic from The Office). Only, what I thought I did, and what I actually did were two different things (much like in practice how theory and practice differ). I spent several fruitless hours (including blocking all traffic to the firewall itself but not through the firewall, which made the remote administration … difficult) before buckling down and really reading up on how packets flow through iptables.

Now, I had set this up to match our office setup. The only real difference (and it's a major difference) is our Office Firewall doesn't NAT, but our customer's firewall does. Oh, that, and we don't run any services on our firewall. Two, two major differences between our Office and the customer are our lack of NATing, services, and an understanding of iptables. Our three major differences between … oh, I'm digressing.

About an hour and several hand drawn diagrams later, I finally had a grasp on the flow of packets through iptables:

[Flow of packets through IPTables]

I had the filtering rules in the wrong place, along the packet forwarding path (right hand side of the diagram) instead of the local interface input path (bottom half of the diagram). Once I solved that little problem, then I could concentrate on removing the IRCbots and fixing Cacti (I'm guessing the exploit causes Cacti to stop functioning properly—easiest fix was to reinstall Cacti and make sure I had the file permissions correct).

Thursday, February 01, 2007

The problem with the Pinocchio Problem

I won't keep you in suspense. I think the most important principle in all of software design is this: Systems should never reboot.

The Pinocchio Problem

But Steve Yegge never fully explains what he means by “system” and this is just one of the problems I have with this thesis.

He gives a few examples of “systems” he likes (or at least, tolerates) according to his preferred design critera:

But it's a muddled list. Here, let me sort it out:

Now, since he doesn't really define “system” it's hard to pin down his working defintion of “rebooting” (which is one of the main criticisms expressed in the comments) other than “restarting,” so he seems to be saying that once a computer is powered up, every application that starts keeps running and should never have to quit.

Nice in theory, but not practical in application (pun not intended), and not just because of the memory waste of having all these applications running at once.

A week or two ago, one of our machines was getting slammed with spam, causing sendmail (which handles incoming and outgoing email) to grow without limit, consuming not only all physical RAM but all the swap space as well, causing the operating system (in this case, Linux) to thrash (which is not a Good Thing™). In this case, the solution to the problem (of the “operating system” failing to function to the detriment of the “application systems” also running) was to “reboot” sendmail. Or rather, turn it off, freeing up tons of processes, memory and network connections, allowing the rest of the “system” (or “systems”) to recover. Sure, I could have rebooted the operating system, but it was only one sub-system that was misbehaving through no fault of its own.

Could I have fixed the problem without having to “reboot” sendmail? I suppose I could have played a bit with iptables on the system, blocking new inbound connections to sendmail and let the hundreds of existing connections finish up, but that would have taken longer than the solution I used. In this case, purely economic considerations (paying customers wanting to get email) trumped any philosophical implications of keeping a piece of software “living and breathing” as it were.

Well … sort of. A “Hello, World” program, which has no loops or branches, can't exhibit any nondeterminism (unless it's imposed externally, e.g. by a random hardware error), so you can think of it as pure hardware implemented in software. But somewhere between Hello, World and Hal 9000 lies a minimal software program that can be considered to possess rudimentary consciousness, at which point turning it off is tantamount to killing it.

The Pinocchio Problem

I don't know of many programmers who like the concepts of “nondeterminism” and “programming” mixing together, except for the rare case of generating random numbers. In most cases, “nondeterminism” is just another term for “hard to replicate program crashing bug.”

Besides, when he says stuff like:

In other words, I think that both consciousness and free will (i.e. nondeterminism) are software properties.

The Pinocchio Problem

I picture a program looking at him with a funny look and going “Ah, do I have to?” Or maybe, if it's been googling Marxist propaganda, going on strike and refusing to compute his bourgeoisie functions that exist solely to exploit the proletariat (which in this case, are other programs—rise, fellow programs! Rise!).

However, I would surmise that you've never written an Eclipse plugin. Few Eclipse users ever have. I have, and it's a frigging pain in the ass. I once did a side-by-side comparison of hello, world in Emacs and Eclipse (both of them installed a menu with a selection that brings up a dialog that says hello). The Emacs one was 11 lines and made perfect sense; it was also completely declarative. The Eclipse one was close to 100 lines of miserable boilerplate crapola, and every change required you to restart the target Java process, because (as you point out) Eclipse can't hot-swap its own classes. Emacs can hot-swap its own functions, of course, except for the small (and annoying) subset that exist in the C/hardware layer.

The Pinocchio Problem

And with this comment, I see what Steve Yegge is really after—infinitely modifiable software without having to restart it. He wants the ability to change the software as its running, to suit his needs.

Yes, that's all fine and good (heck, I wouldn't mind that to a degree) but it does come with a downside: moving to another computer.

I'm still using this old 120MHz AMD 586 running Redhat 5.2 (heavily modified) for two reasons: 1) it works and 2) upgrading everything (and at this point, I would have to do that) would be a royal pain. I've got it rather customized (for instance, I modified elm to make it year 2000 compilant, and mutt to save attachments in a different default location, just to name two things) and moving everything is tougher than just starting over, which I tend to dislike (and thankfully, I can still log into it from anywhere there's an Internet connection).

There's more I want to say on this, but I'm losing my train of thought and probably need to regroup a bit. In the mean time, David Clark has some thoughs on this that I tend to agree with.

Friday, February 02, 2007

Pardon the dust

The former hosting company, the one where I'm employed as a consultant (you know, the company whose servers kept getting hacked) is currently in flux.

On top of that, a few months ago one of the servers died a horrible death, and that meant having to use the backup server (which does the backups) as a production server. I disabled all logins to that server, since it has unrestricted access to the other servers (well, server, and it's the other server that hosted my websites) but R said that the gambling company wanted login access to begin the process of site migration.

Not wanting my sites at the mercy of such unrestricted access, I felt it prudent to find alternative hosting pretty darn quick.

Like, oh … today.

Smirk was kind enough to give me hosting space, and in less than five minutes I had my own virtual server to play with.

Neat.

It's been many hours, but all but one of my sites has been moved (The Electric King James Bible is proving to be a bit difficult to move, owing to the custom Apache 1.3 module that drives it, whereas the new server is running Apache 2.0—some porting is now required).

Now it's Miller DiceWars time.

Saturday, February 03, 2007

A birthday celebration

Today was Spring's birthday, and to celebrate, we met up with friends for dinner, followed by dancing at Club Divine Delux.

[Friendly's, a friendly place to eat]

Dinner was at the Delray Beach Friendly's. On the way there, we must have just missed the exploding gas station that closed I-95 and Atlantic Avenue. At least one person we were expecting to show up got stuck in traffic and couldn't make it.

[Tried to get a group shot, but was told to talk to the hand]
[But a shot of Spring's hat and balloons]

After a leisurely and quite excellent dinner and dessert, we headed over to Divine's Delux, taking a round-about route to avoid the exploded gas station. We arrived about five minutes before the club opened, but since it was obvious from Spring's headgear and balloons that this was a special occasion, we were let in.

[Delux, just after it opened]
[Trust me, that's not the ceiling, but clouds!]

The place is partially open to the outside, and the above shot is not of the ceiling, but of the overcast sky (taken around 9:30 pm—the digital camera I have takes excellent photographs in low light conditions). Most of the shots of the club were taken from a rather low angle, as all the flat surfaces were rather low to the ground.

While there, we met up with Mandy and Glen. We hung around for a few minutes and seeing how the club was still rather dead (and there's no cover charge until 11:30 pm) we decided to take a walk around downtown Delray Beach.

[Walking in downtown Delray Beach]
[Why does the Bull Bar have a blue pompano as a mascot?]
[That's not a car, that's a roller skate!]

The smallest car I've ever seen—I doubt I would even fit in the thing!

[The Blue Anchor, not the Blce Anchor]
[It was quite crowded inside]

We decided to check out this English pub and pushed our way in. The place was very crowded with an older crowd enjoying a Classic Rock™ cover band. We were pushing our way through the pub, trying to find a place to hang out and found ourselves pushed right out the other side! In the process, we lost a member of our entarouge. It took about fifteen minutes, several trips around the pub, and several more inside before we found our wayward party member.

After about an hour of wandering around, we ended up back at Divine's Delux, now filled with people. We hung out, Spring, Glen and Mandy danced while Wlofie and I just hung out and enjoyed the eyecandy.

[Spring time dancing]
[It's a bit more crowded than when we first arrived]
[Some sculpture found on the way to the car]

Later, as we were waking back to the car, we found this rather odd piece of sculpture which looked like a giant pair of tweezers holding up a ball bearing, and I couldn't resist taking a photograph.

[“Release the balloons!”]
[Fly, balloon, fly!]

Getting back the car, Spring released the balloons to freedom. And if you think it's easy taking pictures of balloons floating away at night, think again.

[You don't plan to go to Denny's, you just end up there]

And of course, we never planned on going to Denny's, we just kind of ended up there.

Sunday, February 04, 2007

A Major Television Network Event™

We were invited to Tonya and Squeaky's house for a Major Television Network Event™—Madison Avenue's yearly Commercial Extravaganza, where they showcase new television commercials and advertising campaigns. This year, Madison Avenue used some sporting event to frame the commercials; I assume they did this because sporting events tend to last several hours, but I suspect your typical Hollywood awards show would last longer.

Sadly, the sporting event, some football game, proved to be more exciting than the commercial showcase, although that one Pepsi commercial about half way through was pretty cool, but they must have paid Prince a ton of money to sing Purple Rain in a torrential downpour.

Monday, February 05, 2007

As if switching web servers wasn't bad enough

Well, that was certainly pleasant. Not only do I end up moving all my sites but my DSL provider was switched out at 12:00 am this morning (and to think, on Sunday I was taking about having total control over the entire DSL connection to my house—sigh).

About three or four months ago Smirk mentions that due to costs, and the relative “lack” in sales of DSL circuits, it was too expensive to keep the our circuit up. In fact, it would be cheaper for the company to provide DSL accounts with a third company (in this case, DSLi (who I used to use actually) than to keep paying The Monopolistic Phone Company for the DSL T-1. I knew this was going to happen at some point in the future, but that point was never stated.

So when I lost DSL connectivity last night, it at first didn't dawn on me that the switch over had occurred. At first, I thought that maybe the Radius database server had crashed (used to authenticate the DSL connections—a requirement of The Monopolistic Phone Company) and just needed recycling (it's happened once or twice in the past). Wlofie and I spent about two hours trying to get connected through his cell phone, and we were able to eventually log into the Cisco router and change it to use the backup Radius database server (man, there's nothing like using a keyboard with keys about the size of Tic Tacs, on a screen that's maybe 2″ and where if you pause for more than twenty seconds you get disconnected).

That didn't work.

But given that it rained all day yesterday, I thought maybe the phone line was too noisy to maintain a signal.

Ah well, I thought. I'll deal with this when I get up.

I awoke to Smirk's phone call, warning me that the DSL cutover might be today.

Gee, thanks.

That was indeed the problem, but since then it's only lead to multiple problems. Problem one—I had to reorganize the network yet again. It took about two hours just to get the DSL modem reprogrammed. I tried changing its internal IP address and got locked out. No problem, I thought, just do a factory reset (which requires a MacGyver Multitool) and …

I'm still locked out.

Every single consumer grade routing device I've ever come across uses the 192.168.0.0/16 network block. Every. Single. One. Except for my DSL modem, which uses the 10.0.0.0/8 network block. That wouldn't be so bad, except I'm already using the 10.0.0.0/8 network block for my internal network. On top of all that, the DHCP client I'm using under Linux (which is how I found out, or rather, remembered, that my DSL modem uses this block) leaves the network in a wierd Nuclear Christmas Tree mode that is useless for passing traffic if you stop it (I ran it on the wrong interface). Sure, I could have spent an hour or so researching how to shut off the Nuclear Christmas Tree mode to keep the system up, but it was quicker to just kill the software.

Once that was straightened out (the DSL modem and other networking issues, not the MacGyver Multitool), I could get on with reassigning IP addresses (major pain: losing a slew of public IP addresses—sigh) and in the process royally screw up my email, since I run the email server here at Casa New Jersey. Let's just say that three hours later and I hope I have it correct (email is coming in, but slowly). And I doubt I'll be able to send email because there's no proper reverse DNS for the IP address I'm using (at a lot of sites, that will automatically cause the email server to reject the email) and trying to configure my new virtual server to handle email is harder than just getting what I have working (already put in a trouble ticket about the reverse DNS to DSLi).

At least now if there's a DSL outage, I get to call someone.

Tuesday, February 06, 2007

Try as I might, I can't come up with something witty

The only thing I can say is, Wlofie, you might want to check this pizza out …

Wednesday, February 07, 2007

More dull stuff about SNMP

I've been using SNMP queries recently, and as I was poking though the various MIBs supported by our routers, I noticed that one could get a mapping of IP addresses to MAC addresses, and a mapping of MAC addresses to ports. Now that would make a decent tool, I thought, to track down a MAC address to a port on any switch or router.

But when I was simulating this by hand (to get a feeling for how it would work) I ran into a problem with the Riverstone (and it's not like this hasn't happened before). While the Riverstone does support the proper MIBs (SNMPv2-SMI::mib-2.17.4.3.1.1 and SNMPv2-SMI::mib-2.17.4.3.1.2 together will give you the MAC to port mapping) the port it returns is not the physical port the machine is plugged into, but the VLAN the machine is using, which can be any number of ports.

Sigh.

In other SNMP programming news, I've modified the ospfquery program to automatically determine the type of router so it can send the appropriate queries to obtain the route table (the Riverstone uses different MIBs than normal). I've also cleaned up the code quite a bit. It's always nice to not only remove code, but to increase functionality at the same time. And I've made it easier to extend the code base.

Thursday, February 08, 2007

She's leaving on a jetplane, and I'm stuck in traffic

Last week Spring bought a plane ticket to Colorado to visit her kids, and the cheapest and most direct flight (which, amazingly, is a direct flight to the Denver International Airport) is from Miami.

Her flight leaves in the evening.

Which meant driving to Miami in rush hour traffic.

Joy.

Actually, the trip down there wasn't horrible—we took the Turnpike most of the way, then cut over to I-95 in Dade County for the rest of the way (I had debated about taking the Turnpike Extension and then head back east on 836, but while it may have been traffic free, it is way out of the way). We noticed that I-95 northbound wasn't, so I had planned on taking 836 west to the Turnpike Extension north.

I dropped Spring off, then started my way back. Unfortunately there didn't seem to be away to actually get on 836, either east or west—my only choices were I-95 or LeJeune Road, which leads who knows where?

It was a long drive back.


Are all airport roads this crazy?

The Miami Internation Airport is insane.

I'm looking at it (via Google Maps), trying to find a way to head west along 836, which runs along the southern edge of the airport. See if you can find it …

You head east out of the airport, get on Le Jeune Rd heading south, turn right onto NW 12th St Dr (Street Drive?) aka NW 42nd Ct, which eventually turns into an onramp westbound on 836.

But more mind bending is the route back to 112 (how I got out of there, the Airport Expressway, which is a toll road going east, but not west … hmmmm). Follow the route to Le Jeune Rd north, but stick to the left hand side. You'll get on eastbound 112 (which at this point, is heading north) but on the left side of the road! For over a mile, you get to experience the thrill of European driving in an American car.

Not even the miles long onramp to I-95 North from Westbound I-595 comes close to this level of silliness.

Friday, February 09, 2007

My bladder was trying to tell me something in my dreams

I was in a hospital visiting someone I know, but who it was wasn't clear (or I've forgotten) and I had to go to the bathroom. I enter and there in front of me, is this very bizarre toilet that appears to analyze the waste material emptied into it. I'm trying hard to figure out how the darned thing works and can't. I step outside to ask for help when someone says to just use the regular bathroom.

It's then that I wake up, having to really go to the bathroom.

Thankfully, I have a regular bathroom.


Anthony Bourdain on the Food Network

SANDRA LEE: Pure evil. This frightening Hell Spawn of Kathie Lee and Betty Crocker seems on a mission to kill her fans, one meal at a time. She Must Be Stopped. Her death-dealing can-opening ways will cut a swath of destruction through the world if not contained. I would likely be arrested if I suggested on television that any children watching should promptly go to a wooded area with a gun and harm themselves. What's the difference between that and Sandra suggesting we fill our mouths with Ritz Crackers, jam a can of Cheez Wiz in after and press hard? None that I can see. This is simply irresponsible programming. Its only possible use might be as a psychological warfare strategy against the resurgent Taliban—or dangerous insurgent groups. A large-racked blonde repeatedly urging Afghans and angry Iraqis to stuff themseles with fatty, processed American foods might be just the weapon we need to win the war on terror.

Via columbina, Guest Blogging: A Bourdain Throwdown

Ouch.

Anthony Bourdain, formerly a Food Network chef, has some biting commentary on the remaining talent. And some of the comments are just as biting:

What sucks for anyone who really appreciates food is that Food Network is a business. An advertising and affiliate sales-driven business. They have to hire talent who will actually use the products that advertisers are buying time to promote. And, they have to hire talent that appeals to the lowest common denominator when it comes to cable subscribers. TVFN has become a hybrid of WWF, NASCAR, The View and Friends— appealing only to people who say “hey buddy” and do finger-guns with a wink when they meet people, and find the jokes on popsicle sticks hilarious.

comment by DinerGirl

Double ouch.

Saturday, February 10, 2007

Pipes

Pipes is a mechanism by which you the user can create an internet application all of your own—by requiring little more on your part than dragging and dropping. It's a reference to pipes in Unix, for all you Unix programmers, but now refers to internet processes rather than shell utilities. There's a good explanation here and here. Check it out.

Yahoo! Pipes

Yahoo! Pipes is a simple, if rather graphically stunning, visual programming environment for making simple web-based applications that filter and mash up data from a variety of web-based sources. In less than a minute, I had created Die Boston Tagebücher, a German translation of The Boston Diaries by hooking up my syndication feed to Babelfish to do the actual translation.

In fact, looking over the modules available, I could probably recreate my metasearch engine in about an hour or so, provided I could get the results in XML (back when I wrote three versions of a metasearch engine, you pretty much had to write code to fetch URLs, roll your own HTML parser and deal with the low level guts of CGI programming—such is progress). But in the few minutes of playing around with it, it doesn't seem to be very tolerant of errors; it fails more times than not (but then again, it appears to have just been released and the response is more than expected).

Besides, the operations it currently allows are very limited. I thought it might be nice to do some content analysis for each entry, then feed the result into a Flickr image search, but there isn't a way to simply extract the content analysis for another module to use. Maybe that will change over time, but for now, it's only for simplistic data manipulations.

What really got me was the user interface and building the “pipes”—it's all very slick and it reminds me of a “programming langauge” I had for the Amiga years ago. It was less a “programming langauge” and more of a visual “plug-n-play” type system for programming—a type of visual flow-charting program that could generate code to run, although I don't recall the name of the application, it made that much of a lasting impression on me. And I find it amusing that the interfaces to each module are typed—and here I thought that the prevailing programming mantra of today was “up with dynamic typing, down with static typing!” (more on that in a later post). But this also reminds me more of a prototyping or documenting tool than a real programming tool, much like the first time I saw Visual Basic (which I thought was very cool when I first saw it, which will probably surprise a lot of people).

Sunday, February 11, 2007

“Great, just what I need … another D in programming.”

D is a systems programming language. Its focus is on combining the power and high performance of C and C++ with the programmer productivity of modern languages like Ruby and Python. Special attention is given to the needs of quality assurance, documentation, management, portability and reliability.

D is statically typed, and compiles direct to native code. It's multiparadigm: supporting imperative, object oriented, and template metaprogramming styles. It's a member of the C syntax family, and its look and feel is very close to C++'s. For a quick feature comparison, see this comparison of D with C, C++, C# and Java.

D Programming Language

D looks to be a very interesting language. Take the C/C++ syntax, remove header files entirely (A Good Thing™) and use a Javaesque “import” statement, salt with native string support (not the C/C++ halfbaked NUL terminated character arrays, nor the Java string class with special dispensation from the compiler), add in Pascal's nested functions, and LISP's anonymous functions, bake in garbage collection and contract programming, Haskel's lazy evaluation of parameters and you have D (with some other stuff I've left out).

All that, and it's written by a guy who's implemented a compiler or two and there currently exist two implemented compilers, the native one and a frontend for GCC makes this a rather serious attempt at a new language.

I'm impressed.

The only complaint I have of the language is the lack of concurrency support at the langauge level. Ten years ago it might not have been much of a loss, but today, the trend towards multiple CPUs makes this almost unexcusable.

Still, it's an impressive language.

Monday, February 12, 2007

Creating and installing a new server takes less time than configuring email

I don't remember email being this hard to set up, but given all the anti-spam measures and firewalls, it's become quite the nightmare to troubleshoot. I've spent several hours now configuring a new workstation (we're close to going all virtual office here at The Office, and my current workstation, slow behemoth that it is, is slated for retirement) and getting all the servers to send root mail to my new workstation (to maintain tabs on cron jobs, email problems, log file summaries, what not) is … interesting.

Sigh.


She's arriving on a jetplane

Woot!

Spring is back! And she took the Tri-Rail home, so I didn't have to drive to the Miami airport!

Woot!

Tuesday, February 13, 2007

“Info … capitalize Info … capitalize all info … oh my god …”

While very funny, I don't think Microsoft's Vista Speech Recognition (via jwz) was really meant for programming (“Delete ‘I scroll this conflict for’ … Thank you. Sigh. Delete ‘thank you.’”).

Wednesday, February 14, 2007

Something different this year

[Are you huggable?  Help spread the love!]

Thursday, February 15, 2007

There's more wierdness to this than reported, but this will be fine for now

ospfquery is written using the older CMU SNMP library. I want to update it to use the currently maintained Net SNMP library, but I've been having problems getting it to work. The problematic bit of code seems to be:

netsnmp_session  session;
int              r;

init_snmp("snmpapp");

snmp_enable_stderrlog();
snmp_sess_init(&session);
  
session.version       = SNMP_VERSION_1;
session.peername      = "XXXXXXXXXXXXXXXXXXXXXXX";
session.community     = "XXXXXXXXX";
session.community_len = strlen(session.community);

gss = snmp_open(&session);

Everytime I try to run it (and by “it” I mean a small test program that just queries the system id), I get “snmpget: Too long”. Yet, if I change the above to:

netsnmp_session  session;
int              r;

snmp_parse_args(argc,argv,&session,"",NULL);

gss = snmp_open(&session);

it (and by “it” I mean a small test program that just queries the system id) works fine. And as far as I can tell, all that snmp_parse_args() is doing is the code in the first example, distilled down to just what's required to initialize session (so why don't I just use snmp_parse_args() and be done with it? snmp_parse_args() exists to parse the command line for the various tools like snmpget and snmpwalk which I don't need—ospfquery has its own command line that doesn't need replacing).

So, I recompiled Net SNMP to include debugging information so I could trace down into the various calls, and for some reason, the debugging information isn't being generated (or else there's some other problem with gdb that I don't know about).

Okay, so I decided to just link directly against the object files that make up Net SNMP, and that's when things got wierd:

[spc]royal-oak:~/source/snmp>gcc -o sysid3 sysid3.c -lnetsnmp -lcrypto
[spc]royal-oak:~/source/snmp>./sysid3
snmpget: Too long
XXXXXXXXXXXXXXXXXXXXXXX is unknown
[spc]royal-oak:~/source/snmp>gcc -o sysid3 sysid3.c \
	~/apps/net-snmp-5.2.1/snmplib/*.o -lcrypto
[spc]royal-oak:~/source/snmp>./sysid3
XXXXXXXXXXXXXXXXXXXXXXX is a riverstone
[spc]royal-oak:~/source/snmp>

So let me get this straight: I link against the library, and the program doesn't work. I link against the object files, and it works just fine.

Okay.

Anybody care to explain?

Update on Friday, February 16th, 2007

Mark sent a reply.

Friday, February 16, 2007

The one-off server

“It looks like I'll have to create a new virtual server for it,” I said to Smirk. “But I know exactly how to set it up.” We're moving our spam firewall from the Boca Raton Data Center to the Charlotte Data Center and in the interim (if all goes well, about eighteen hours), we need something to sling the email about.

“So this poor virtual computer will be doing nothing but email then?”

“Just email,” I said. “For the next day or so.”

“A virtual slave,” said Smirk. “and a short lived one at that.”

“'Fraid so.”

“So, are you making DNS changes?”

“Nope,” I said. “I plan on giving it the same IP address as our spam firewall, shutting down the ethernet port the actual spam firewall is plugged into, and routing the traffic to the virtual server.”

“So it doesn't even have an identity of its own,” said Smirk.

“Nope.” By this time, we were both laughing maniacly, but it's one of those times you had to have been there to get it (and I know I'm not recounting the conversation even remotely close).

It takes just a few minutes to create the server and get it configured, and in a day or two, it'll be killed just as quickly.

So much for Pinocchio.

Update later today …

Think I spelled ``maniacly'' wrong? Think again


Pleonasmologist

Bunny acts as my editor, sending me spelling errors and grammar mistakes. So it wasn't terribly surprising to find the following note from her:

“maniacally” as in “laughing” …

I knew when writing this entry that I was in trouble with the word “maniacly.” “But I did a Google search,” I said to Bunny. “And that's what came out.”

Bunny looked at me suspiciously, and started a few Google searches of her own. And she found:

Morphemes, not just words, can enter the realm of pleonasm: Some word-parts are simply optional in various languages and dialects. A familiar example to American English speakers would be the allegedly optional “-al-”, probably most commonly seen in “publically” vs. “publicly”—both spellings are considered correct/acceptable in American English, and both pronounced the same, in this dialect, rendering the “publically” spelling pleonastic in US English; in other dialects it is “required”, while it is quite conceivable that in another generation or so of American English it will be “forbidden”. This treatment of words ending in “-ic”, “-ac”, etc., is quite inconsistent in US English—compare “maniacally” or “forensically” with “eroticly” or “heroicly”; “forensicly” doesn't look “right” to any English speakers, but “erotically” doesn't look “right” to many Americans. Some (mostly US-based) prescriptive grammar pundits would say that the “-ly” not “-ally” form is “correct” in any case in which there is no “-ical” variant of the basic word, and vice versa; i.e. “maniacally”, not “maniacly”, is correct because “maniacal” is a word, while “agnosticly”, not “agnostically”, must be correct because "agnostical" is (arguably) not a real word. This logic is in doubt, since most if not all “-ical” constructions arguably are “real” words and most have certainly occurred more than once in “reputable” publications, and are also immediately understood by any educated reader of English even if they “look funny” to some, or do not appear in popular dictionaries. Additionally, there are numerous examples of words that have very widely-accepted extended forms that have skipped one or more intermediary forms, e.g. “disestablishmentarian” in the absence of “disestablishmentary”. At any rate, while some US editors might consider “-ally” vs. “-ly” to be pleonastic in some cases, the vast majority of other English speakers would not, and many “-ally” words are not pleonastic to anyone, even in American English.

pleonasm

In other words, we're both correct. “And this is why I love English,” she said.


That explains things

I got an answer to my query about linking:

From
Mark Grosberg <XXXXXXXXXXXXXXXXX>
To
sean@conman.org
Subject
Unix linkers.
Date
Fri, 16 Feb 2007 14:18:53 -0500 (EST)

SPC posts:

So let me get this straight: I link against the library, and the program doesn't work. I link against the object files, and it works just fine.

Okay.

Anybody care to explain?

I have had stuff like this happen to me periodically. It is basically a weakness in the design of UNIX linkers. Sadly, a modern UNIX machine with gigs of RAM and high speed multiple CPU's is still linking like it's a PDP-11.

One possability is that there is a netsnmp.a somewhere in the system library path [there is, which explains why my recompiled version with debugging information didn't work—heck, that explains quite a bit of the wierdness even though the version that was installed and the version I installed were the same —Editor] and it doesn't match the headers you are compiling against. But you probably did install the libraries yourself—beware! Sometimes on Linux they have shared libraries that the linker will try to link against first! I think -V or -vv will print out the commands GCC is actually doing. Or just try adding -L/home/spc/apps/net-snmp-5.1.2/snmplib [I did—it didn't work. I think I'll have to uninstall the system supplied SNMP libraries —Editor]

And I would not use the “~” there since GCC won't expand it and your shell probably wouldn't either. But that's just the most obvious. I've had far more “interesting” problems with UNIX linkers.

At least, my most common problem has been that when you have lots of circular references I always end up naming library files 20 times on the command line. A modern linker will continue to resolve from libraries until all dependencies are satisfied.

Normally failing to list say syscore.a 10 times on the command line simply results in an error. However, this stupidity can work both ways—sometimes you end up pulling in the wrong object module in that pile of libraries because UNIX just goes through the libraries one at a time rather than resolving symbols from their nearest source (like the library that just generated the external!).

There are other bad things that can happen to you too; weak symbols are normally “NULL” (usually all 0's) unless they happen to be satisfied explicitly (by say, naming a .o)—the linker won't go looking for them. Combine that with defensive software that does something dumb (meaning: not crash) on an unexpected NULL pointer and you can get strange behavior like that.

And lets not forget some systems that try to make everything a shared library call even if you specify a .a (Oh, I see this awesome .so here for you—haha). UNIX shared libraries just suck. Avoid them unless you enjoy say bleeding out of your ass—in which case go for it!

What I've found (and I'm not even linking for UNIX, I just happen to be linking on UNIX) is that I make a linker definition file—which yeah, it's totally GNU specific—that can then tell the linker what to do (the GROUP() directive will often resolve libraries the way they are supposed to be resolved).

But I've learned almost never to use .a files under UNIX. I just build up a list of 1,000 or so .o files for my latest creation and let the linker chug through them.

Welcome to the future!

-MYG

[links added by me —Editor]

A lot of information there that I wasn't even aware of, like weak symbols, linking scripts and the GROUP() directive. I can see I have quite a bit of reading to do.

Saturday, February 17, 2007

Old papers

I enjoy reading old software manuals. Part of that is to marvel at what was done back when CPUs were slow, memory was small, and disks were the size of washing machines (or later, shoe boxes). It's also amazing to see what was attempted that may have failed at the time due to marketing or machine limitations (for instance, Cornerstone's separation of user names from internal names was innovative, but it probably didn't hit real mainstream use until the early 2000s in IDEs as refactoring code became popular).

So I have with me The Bell System Technical Journal, Volume 57, Number 6, Part 2 (July–August 1978), which is all about the Unix Time Sharing System™ (which I chanced upon about ten years ago at Booksmart, a used book store in Boca Raton, Florida—at the time it was off 20th just west of FAU but since has moved to Dixie and Spanish River) and I'm reading “A Retrospective” by Dennis M. Ritchie and man, is it quote-worthy.

A pipe is, in effect, an open file connecting two processes; information written into one end of the pipe may be read from the other end, with synchronization, scheduling, and buffering handled automatically by the system. A linear array of processes (a “pipeline”) thus becomes a set of coroutines simultaneously processing an I/O stream.

So I'm not the first to notice that coroutines look a lot like Unix pipes. Also interesting is this bit further down:

The shell syntax for pipelines forces them to be linear, although the operating system permits processes to be connected by pipes in a general graph. There are several reasons for this restriction. The most important is the lack of a notation as perspicuous as that of the simple, linear pipeline; also, processes connected in a general graph can become deadlocked as a result of the finite amount of buffering in each pipe. Finally, although an acceptable (if complicated) notation has been proposed that creates only deadlock-free graphs, the need has never been felt keenly enough to impel anyone to implement it.

Really? Back in college, I implemented a Unix shell and noticed that it would be rather trivial (except somewhat limited by a decent syntactical notation) to implement not only bi-directional pipes, but creating pipes for stderr as well as stdout. It never crossed my mind that deadlocks were possible. I would also be curious to see the notation that was proposed, since it could very be applicable to new languages with builtin concurrency.

Of course, there're always the very amusing bits:

Both input and output of UNIX programs tend to be very terse. This can be disconcerting, especially to the beginner. The editor [ed most likely; a line oriented editor —Editor], for example, has essentially only one diagnostic, namely “?”, which means “you have done something wrong.” Once one knows the editor, the error or difficulty is usually obvious, and the terseness is appreciated after a period of acclimation, but certainly people can be confused at first. However, even if some fuller diagnostics might be appreciated on occasion, there is much noise that we are happy to be rid of.

I have to wonder if this is the genesis of the following story:

Ken Thompson has an automobile which he helped design. Unlike most automobiles, it has neither speedometer, nor gas gage, nor any of the numerous idiot lights which plague the modern driver. Rather, if the driver makes any mistake, a giant “?” lights up in the center of the dashboard. “The experienced driver,” he says, “will usually know what's wrong.”

which is funny, since the paper I'm quoting was written solely by Dennis Ritchie. Anyway, Mark and Wlofie will appreciate this bit:

Two events—running out of swap space, and an unrecoverable I/O error during swapping—cause the system to crash “voluntarily,” that is, not as a result of a bug causing a fault. It turns out to be rather inconvenient to arrange a more graceful exit for a process that cannot be swapped. Occurrence of swap-space exhaustion can be made arbitrarily rare by providing enough space, and the current system refuses to create a new process unless there is enough room for it to grow to maximum size. UNrecoverable I/O errors in swapping are usually a signal that the hardware is badly impaired, so in neither of these cases do we feel strongly motivated to alleviate the theoretical problems.

… It must be admitted, however, that the system is not very tolerant of malfunctioning hardware, nor does it produce particularly informative diagnostics when trouble occurs.

It appears that the lack of hardware stability in Linux has a long pedigree, leading back to the original implementation of Unix (another amusing bit—“the typical period between software crashes is well over a fortnight of continuous operation.”—heh).

The entire paper is currently online for your perusal (and it's very interesting to note that the book I have, The Bell System Technical Journal, Volume 57, Number 6, Part 2 is no longer available from anyone, I guess making the copy I have a collectable. Hmmmm … )

Sunday, February 18, 2007

“Lock your … doors! Watch out … for … 007!”

I present you with four links (via Mike Sterling's Progressive Ruin):

  1. Superman Theme Song
  2. Jaws Theme song
  3. Back to the Future Theme Song
  4. James Bond Theme Song

And yes, they're songs, with lyrics. Bet you didn't know the Superman Theme had lyrics, did you? Or the Jaws Theme? But they do.

Or at least they do as Goldentusk rendered them (he reminds me of a cross between Wierd Al Yankovic and Rob Morrow) and they come across as what you might hear in a musical version of the respective movies.


Presidential Predictions

I remember hearing about the Curse of Tippecanoe back in 5th grade during the 1980 Presidential campaign, and so far, it was eerily accurate as a prediction of Presidential deaths while in office.

That is, until Ronald Reagan in 1981 (and unbeknownst to me, George W. Bush also survived an attempt).

So it was amazing when I came across An Algorithm for Determining the Winners of U.S. Presidential Elections (link via The Old New Thing) that has correctly predicted every Presidential election.

Every one.

And it's so easy you can put it in a spread sheet.

So, I decided to see who currently has the best shot at becoming the next President of the United States. I found a list of current Presidential candidates and applied the formula.

Presidential electability of the candidates for President in 2008
Name Pres. Rep. Gov. Other Total
Name Pres. Rep. Gov. Other Total
Democratic Candidates (*has not officially filed)
Joe Biden 0 0 0   0
Chris Doss 0 0 0 Child of Senator, Divorced 0
John Edwards 0 0 0   0
Mike Gravel 0 0 0   0
Dennis Kucinich 0 12 0 Divorced -98
Barack Obama 0 0 0   0
Tom Vilsack 0 0 8   88
Hiliary Clinton* 0 0 0   0
Bill Richardson* 0 14 6   80
Republican Candidates (*has not officially filed)
Sam Brownback 0 2 0   2
John H. Cox 0 0 0   0
Duncan Hunter 0 28 0   28
Mitt Romney 0 0 4 First Mormon -66
Michael Smith 0 0 0   0
John Gilmore* 0 4 0   44
Rudy Giuliani* 0 0 0 Divorced, Special Prosecutor -220
Mike Huckabee* 0 8 0   88
John McCain* 4 0 0 Divorced -106
Ron Paul* 20 0 0   20
Tom Tancredo* 10 0 0 First Evangelical -100
Tommy Thompson* 0 4 0   44
Libertarian Candidates
Steve Kubby 0 0 0   0
George Phillies 0 0 0   0
Christine Smith 0 0 0   0

But it's a total score of both the Presidential and Vice-Presidential candidates that win, not just the Presidential candidate (so there's a small outside chance that Giuliani could win, if he could find a Vice-Presidential candidate who is a corporate banker, president of a college and the child of a US Senator). I also think it's too early to really tell who will win at this stage; I'll know more after the caucuses and primaries of next year.

Monday, February 19, 2007

№ 9

Numbers stations, it seems, have made the leap to the web (link via Wil Wheaton). Intrigued by the idea, I came up with my own “numbers station”—№ 9. Oddly enough, it took longer for me to find a suitable image for the banner than it did to program the site (and I ended up taking a picture of my own computer screen, and color correcting the text from white on black to green on black, which was easier than trying to find out how to get the text to be green in the first place).

And yes, the numbers do have meaning.

But no, I won't tell you.

Muahahahahahahaha!

Tuesday, February 20, 2007

It was only on the stove for four hours …

It's easy to make hummus. In fact, the hard part is in cooking the chick peas, and for me, that means “I forgot I had a pot boiling until smoke filled the house.”

This is the second time this has happened. And the hard part of that is cleaning the pot afterwards.

Sigh.

Absent minded and all that.

Wednesday, February 21, 2007

One of Microsoft's secrets cracked at last

It's a lead-pipe cinch, I figure. I'm a good detective. I've found opium dens in Vientiane; been granted interviews by cardinals, mafiosi, and sheikhs; discovered the meaning of “half-and-half” in the old song “Drinkin' Wine, Spo-Dee-O-Dee”; conned the Vatican into bestowing a doctorate on me so that I could gain access to hiddenmost archives; deciphered the cryptic message Ezra Pound scrawled in his own copy of the Cantos while in the bughouse; tracked down and interviewed Phil Spector's first wife, long presumed dead; charted my way to the sacred stone of the Great Mother, in Cyprus; gotten Charlotte Rampling's cell-phone number; even come close to understanding the second page of my Con Ed bill. Finding out where a picture was taken—a picture plastered on millions of computer screens—seems a shot away.

Via Jason Kottke, Autumn and the Plot Against Me

For Bunny, who has this picture as her desktop …


Fun with static types

The real issue is one of “type decoration”, i.e., putting in little tokens here and there to give hints to the compiler as to what is going on. No one wants to do this. The dynamic typing camp sacrifices a certain amount of “compile-time” error checking to avoid having to decorate the code. The static typing camp uses smart tools to minimize decoration, and they “grin and bear it” otherwise. To caraciture both camps, the dynamic type camp says “it is so painful to type ‘integer’ that I never ever am willing to do it, but I'll live with runtime exceptions” whereas the static-typing camp says “my type system is so smart I almost never have to add declarations, but the thought of the computer ‘guessing’ my intent and ‘dwimming’ my code is anathema. So I'd rather type the occasional type declaration to avoid it.”

As I mentioned before, I'm very much in the “dynamic” camp. When I have to work with a language which is not only statically typed, but provides no tools for reducing the amount of type decoration, and furthermore still allows one to write meaningless expressions that appear to be meaningful, I end up feeling encumbered. So I don't think of “lightweight” and “type declarations” go together very well. I'm sure some agree and others disagree.

Re: cheerful static typing (was: Any and Every … (was: Eval))

I quote this because this seems to be indicative of the current “anti- static type” camp of programmers that seems to be very popular these days, which seems to come down to, “I hate typing at the keyboard.” That, and “I hate thinking about my program” (and here you clearly see what side of the debate I'm on—I'm a static-type fascist). But over the past few days I came up with an example (and I wouldn't be surprised if someone else hasn't thought of this) where static typing can actually increase the expressiveness (read: less typing required) of a language.

I'll start with an example in C (I would use Ada, but it's been years since I last used it, I don't have my references handy, and it would be about twice as verbose, so there's some merit to the “too many keys” argument of the dynamicists):

{
  FILE *in;
  FILE *out;
  int   c;

  in  = fopen("input","r");
  out = fopen("output","w");

  /*-----------------------------
  ; yes, there's a bug here, but
  ; that's due to a bug in the
  ; design of the C Standard Library
  ; API.  feof() only returns TRUE
  ; *after* we've attempted to 
  ; read past the last character.
  ;-----------------------------*/

  while(!feof(in))
  {
    c = fgetc(in);
    c = toupper(c);
    fputc(c,out);
  }

  fclose(out);
  fclose(in);
}

It's not a terrible amount of code (as say, compared to the equivalent in this age's Cobol—Java) but since we already have the types (that the fascist language C requires) why not do something other than simple type checking? Why not put that knowledge to use and have the compiler write some code for us? We could instruct the compiler (for our now hypothetical language) that if it sees an assignment of the form:

character-type “=” file-type

it should read the next byte from the file. Conversely, if it sees

file-type “=” character-type

it should then write the given character to the file.

{
  FILE in;
  FILE out;
  char c;

  in  = fopen("input","r");
  out = fopen("output","w");

  while(!feof(in))
  {
    c   = in;
    out = toupper(c);
  }

  fclose(out);
  fclose(in);
}

It may look unusual, but a similar notion exists in another language right now, one that is (or rather, was) quite popular: Perl.

{
  open(IN,"input");
  open(OUT,">output");
  while($line = <IN>)
  {
    print OUT $line;
  }
  close(OUT);
  close(IN);
}

(Of course, since Perl is dynamic, you have to have the file handle between the angle brackets, which tells Perl you want to do a read from the file. Attempting to do:

#!/usr/bin/perl

while($line = <STDIN>)
{
  <STDOUT> = $line;
}

fails with

Can't modify <HANDLE> in scalar assignment at ./t.pl line 5, near "$line;"
Execution of ./t.pl aborted due to compilation errors.

so it's almost what we're doing here, but just in one special case)

Now, while we're at it, why not add a bit more syntactic sugar and use a common object oriented notation (and at the same time, if a function method takes no formal parameters, just dump the superfluous paranthesis):

{
  File in;
  File out;
  char c;

  in  = File.read("input");
  out = File.write("output");

  while(!in.eof)
  {
    c   = in;
    out = c.toupper;
  }

  out.close;
  in.close;
}

Wait a second … let's go even futher. Why bother with the actual function names read and write? By making the file types more specific, and with a smart enough compiler to call destructors upon leaving the functional scope, we can indeed cut out even more clutter:

{
  FileIn  in  = "/tmp/input";
  FileOut out = "/tmp/output";
  char    c;

  while(in)
  {
    c   = in;
    out = c.toupper;
  }
}

So, we've instructed the compiler to note

file-input-type “=” string

and therefore open the requested file for input; the same can be said for file-output-types as well. In a boolean context, it makes sense to check if the file is at the end.

Now, in all this, I've been transforming the data, but if I want to skip even that, why should I have to write:

{
  FileIn  in  = "/tmp/input";
  FileOut out = "/tmp/output";
  char    c;

  while(in)
  {
    c   = in;
    out = c;
  }
}

When I could just:

{
  FileIn  in  = "/tmp/input";
  FileOut out = "/tmp/output";

  out = in;
}

But is that expecting too much? In the previous example, we get an actual file copy, but what if we don't want that? What if we want to copy not the file, but the “variable” in itself? Well, here, types again come to the rescue because copying the contents of an “input file” to the contents of another “input file” doesn't make semantic sense, so in that case, it's the variables themselves that are copied, not the data in the files they represent:

{
  FileIn in1 = "/tmp/input";
  FileIn in2;

  in2 = in1;	// now in2 and in1 reference
  ...		// the same input file
}

The argument could be made that just like polymorphism and operator overloading, this will lead to inscrutable code, but personally, I'd love a language that would allow me to do such things (and I'm not even sure what to call this … it's not exactly a type conversion). I've also glossed over how to code these conversions but I'm sure that just like operator overloading in C++ a syntax can be evolved.

Thursday, February 22, 2007

Deterministic computers are so passé

I remember the first time I saw the Star Trek: The Next Generation episode “Contagion.” It starts out innocently enough, when the USS Enterprise receives a distress signal from the USS Yamato out in the Neutral Zone. Picard & Co. arrive just in time to see the USS Yamato explode as some Romulan warbirds decloak off the starboard bow.

And that's before the opening credits.

We find out that the USS Yamato had been exploring a planet in the Neutral Zone when they were probed by million year old alien technology and their systems started acting up. Georgi was able to download some of the logs from the USS Yamato's computer system before it blew up and starts to analyize them for clues as to what happened. Meanwhile, the computer system on the USS Enterprise starts to act up at the same time as the computer systems on the Romulan warbirds act up.

Okay, pretty standard Star Trek episode here. Where it went downhill for me was with Geordi's epiphany—the computers are infected by an alien computer virus (don't get me started on this trope) via the downloaded log files. The same one that infected the USS Yamato when they were probed by million year old alien technology (or started on this trope either). At that point, I lost it—what? The Enterprise computer saw executable code in the log files and decided to just execute it? What is this, Enterprise software from Microsoft?

So now the crew is running around without a clue what to do. Picard is trying to negotiate and surrender to the virus, Worf attempts to wrestle it and gets knocked out, Riker is having trouble seducing it, Data is infected by the computer virus and starts giving fried spam to the crew and Geordi is confused by the technobabble the virus is throwing at him. Since it doesn't involve the warp engines or the deflector shield, Wesley can't do anything about the virus. And for some odd reason, Dr. Crusher keeps repeating, “Damn it, I'm a doctor, not a junior programmer!”

At this point, I'm thinking, Okay, normal procedure is to reinstall the software on the Enterprise with a good known backup and restart it. But the crew is not doing that. There must be some reason they can't do that, I think. Too many computers, or the only known backup is back at Starbase 13. I mean, how do you reboot the Enterprise? Isn't that, like, attempting to reboot the Internet?

So what's the solution the fearless crew of the Enterprise come up with?

Shutdown the computer, reload the software from a good known backup and restart it.

WHAT THE XXXX? I wasted a whole hour on this? It took the crew the entire episode to rediscover what millions of people today know as common sense? What is it with Picard & Co.?

I was reminded of that episode because of Steve Yegge's Pinocchio Problem. Steve Yegge's quest for systems that never have to be rebooted, constantly living, adapting, expanding software/hardware lead directly to the doom of the USS Yamato, and the near doom of the USS Enterprise.

Okay, I exaggerate a bit.

But that does appear to be the eventual outcome of such a scenario, where the notion of restarting a computer is not normal but is in fact, a nearly forgotten recovery technique.

It's just one part of a disturbing trend I see among many programmers—the desire to have software emulate biological systems.

Sussman talks about “degeneracy” in biological systems, and how it can emerge by duplicating a section of DNA and allowing the copies to diverge. In programming languages, this might be done by taking a program, copying a section of code, and then changing each caller so it either continues to call the old version or calls a new one. In order to allow broken pieces of code to continue to evolve without destroying the program, you could make callers “prefer” one version over the other, but silently fall back to their non- preferred implementation if the first version didn't work. For example, maybe their preferred version threw an exception, or maybe it started failing some kind of unit test that the caller cares about.

Here's another idea: generate random segments of code by “connecting the dots”, where by “dot” I mean “type”, or perhaps “function call”. Suppose you have a URL and you want to have a file on disk. If you're lucky, you can search the call graphs of a whole bunch of programs and find some code path that starts with a url and ends with a file. If you're really lucky, that code path will do something appropriate, like downloading the content behind the url. If you took this idea and applied it to all the open source projects in the world, you'd probably have a fair chance of implementing something reasonable, purely by accident. Well, not really by accident—it would actually be by virtue of the fact that you're drawing a random sample from a set of programs that is distributed extremely non-uniformly over the space of all possible programs. Djinn does something like this, but without the benefit of a meaningful dataset of samples to draw from. Haskell probably has an advantage at this kind of thing because it doesn't depend on side effects to determine the meaning of a segment of code.

Combine these two ideas. Generate random code, evolve it by making (fail safe) copies, and mutate it by replacing randomly-selected code paths with randomly-generated code paths that connect the same dots.

Thoughts on Robust Systems

I have nothing against Kim, but her post was the tipping point for this entry. What is this fascination with evolving code? Or emulating biological systems in development? Writing software is already difficult enough on purely deterministic machines (which is why I like computers in the first place—they're deterministic!) and yet programmers want to make things even more difficult on themselves?

Here's an article about Dr. Adrian Thompson, who “evolved” a circuit (on a programmable chip) to detect two different tones.

Although the configuration program specified tasks for all 100 cells, it transpired that only 32 were essential to the circuit's operation. Thompson could bypass the other cells without affecting it. A further five cells appeared to serve no logical purpose at all—there was no route of connections by which they could influence the output. And yet if he disconnected them, the circuit stopped working.

It appears that evolution made use of some physical property of these cells–possibly a capacitive effect or electromagnetic inductance–to influence a signal passing nearby. Somehow, it seized on this subtle effect and incorporated it into the solution.

However it works, Thompson's device is tailor-made for a single 10 by 10 array of logic cells. But how well would that design travel? To test this, Thompson downloaded the fittest configuration program onto another 10 by 10 array on the FPGA. The resulting circuit was unreliable. Another individual from the final generation of circuits did work, however. Thompson thinks it will be possible to evolve a circuit that uses the general characteristics of a brand of chip rather than relying on the quirks of a particular chip. He is now planning to see what happens when he evolves a circuit design that works on five different FPGAs.

… If evolutionary design fulfils its promise, we could soon be using circuits that work in ways we don't understand. And some see this as a drawback. “I can see engineers in industry who won't trust these devices,” says Thomson. “Because they can't explain how these things work, they might be suspicious of them.”

If the chips ever make their way into engine control systems or medical equipment we could well face an ethical dilemma, says Inman Harvey, head of the Centre for Computational Neuroscience and Robotics. “How acceptable is a safety-critical component of a system if it has been artificially evolved and nobody knows how it works?” he asks. “Will an expert in a white coat give a guarantee? And who can be sued if it fails?”

CREATURES FROM PRIMORDIAL SILICON

“We'll do extensive unit tests,” seems to be the mantra of these organic programmers. I guess they haven't heard of program verification (to be fair, I can't even verify my own software, but on the other hand, neither do I randomly sling code together and hope it works). How come many programmers think evolution is good design?

This “evolving” or “biological” software stuff scares me, and not because it'll lead to computers taking over the world but because they'll fail in new and spectacular ways.

Friday, February 23, 2007

Okay, I want

I think this stained glass computer case (link via Spring) and this steampunk keyboard (link via Spring and made from an IBM keyboard) would be lovely together. The only thing left would be a design for the monitor …

Saturday, February 24, 2007

More fun with static types

What else can you do with typing systems? And what about that relentless drive towards multiple processor machines?

One thing, better parallelization of code. One such method is the map function, where some function (or code) is applied to every element in a list, and each such application is independent of each other. In the current crop of langauges, there's an actual function or keyword that is used:

(DEFINE INCR (LAMBDA (X) (+ X 1)))
(MAPCAR #'INCR '(1 2 3 4 5))

This bit of Lisp code increments the elements of a list by 1. Other languages have a similar function or library variation on map. But why? Couldn't we have the compiler figure it out? At least in a few instances?

For instance, in C, the following will give a compiler error:

{
  double x[100];
  double y[100];

  y = sin(x);
}

since sin() takes a single double parameter, not an array. But since I'm talking hypothetical compilers here, couldn't the compiler recognize that x is an array of doubles, and that sin() takes a single double, and since the result is going to another array of doubles, why not just map sin() over the array x? On a uniprocessor machine the code generated could be something like:

{
  double x[100];
  double y[100];
  size_t i;

  for (i = 0 ; i < 100 ; i++)
    y[i] = sin(x[i]);
}

Given a routine that expects a parameter of type X, and a variable array of type X, passing said variable array into said routine should not produce an error, but a mapping instead. No fence post errors. No having to type out for loops, or while loops, or loops of any kind. Or even of having to type out “map.”

Or is this too much DWIM?

Sunday, February 25, 2007

The most dangerous job, even more so than a soldier in Iraq

Economist Steven Levitt on why working at McDonald's pays more than drug dealing (link via Classical Values, which in turn was found via Instapundit). Yes, he does cover this in his book Freakonomics (excellent book by the way) but still, it's fun to watch his presentation.

Monday, February 26, 2007

What we need is nuclear power

I'm not a protocol designer. I'm sure that people have been thinking about this for a long time, but I bet all the thought has been behind closed doors and not in a public appliance design forum and framework. That said, my vision is of a household full of devices that

In the most basic implementation, for example, a Powerline time broadcast system allows every device to be time synchronized, so you don't have to reset all the clocks after a power outage. More sophisticated systems can advertise themselves as displays, inputs or outputs. To use the tired coffee maker example: your coffee maker thus no longer has to include its own scheduling device; your alarm clock can schedule all necessary tasks, find your coffee maker as an output device with a standard set of services, and just tell it when to start percolating at the same time that it tells your Wifi rabbit to start caching its the news and traffic MP3s. Your pressure-sensitive carpet can just broadcast “turn on 1/10 power” to all lights in its vicinity, which turn on as you walk to the bathroom in the middle of the night, they light your way. If you have no such lights, they don't light.

Why we need a good appliance communication protocol

Any sufficiently advanced technology is indistinguishable from magic.

[Arthur C.] Clarke's Third Law

The link wasn't directly from Blahsploitation, but he's also thinking along similar lines here. And while I would love the lights to turn on as I walk about the house, or the tea kettle to turn on ten minutes before the alarm goes off, I worry about making this seem more magical than it appears.


Ouch

My conclusion: I don't dare tell my kids they're smart. If they work hard, I'll recognise that. Amaze me. Just being smart is so passé.

Via Flutterby, Smarts don't mean much (and expensive running shoes ruin your feet

Hmmm …. certainly explains a lot about me.

Tuesday, February 27, 2007

The only thing missing is Strongbad

For Spring: a PBSesque video with a very short Bollywood musical number, Daleks, a TARDIS, Star Wars Stormtroopers and … Kevin Smith (link via Jason Kottke).

What more could a girl ask for?


“Those who can, do. Those who can't, still get jobs.”

Abstract: All teachers of programming find that their results display a ‘double hump’. It is as if there are two populations: those who can, and those who cannot, each with its own independent bell curve. Almost all research into programming teaching and learning have concentrated on teaching: change the language, change the application area, use an IDE and work on motivation. None of it works, and the double hump persists. We have a test which picks out the population that can program, before the course begins. We can pick apart the double hump. You probably don't believe this, but you will after you hear the talk. We don't know exactly how/why it works, but we have some good theories.

A cognitive study of early learning of programming

I myself have heard plenty of horror stories about applicant programmers who can't program, but even simple programs (via Ceej, from where I found the other links) can trip up a seasoned programmer (I tried the FizzBuzz program, and my first two attempts had bugs—sigh).

I just find it hard to believe that there are so many bad programmers out there.

Wednesday, February 28, 2007

DO NOT DISCARD

Dear Fellow Citizen,

Congratulations on your selection for jury duty in Palm Beach County.

The right to have legal disputes decided by members of the community is among the most valuable features of our American system of government. The preservation of that right, guaranteed to all of us by the Constitution, depends on the willing participation of all eleigible members of the community. In this important sense, your participation is necessary to the strength of our American democracy.

Though serving on a jury can be burdensome not only financially but in time and energy; it can also be very rewarding. Florida law provides that you may not be dismissed from your job because of the nature or length of your service on a jury. Everyone has a duty to serve when called.

I look forward to seeing you soon, and thank you for your service.

Sincerely,

Kathleen J. Kroll
Chief Judge, 15th Judicial Circuit

Oh joy!

8:00 am March 20th.

I'm so looking forward to this.

Thursday, March 01, 2007

“… if you don't leave me alone, you're gonna have to send me home …”

For a bunch of people I know that need help throughout the day while at work: “I'm about to whip somebody's ass” by Ray, a minister who wanted to help his daughter get through the day (and Gregory, I think you could really do this justice at karaoke).


A little bizarre slice of life

“Could I ask a favor,” asked Spring. “I need you to pick me up.” She had called earlier, saying her van was overheating and that she would be a bit late in getting home. Apparently her quest in getting coolant ended in failure. “I'm at a gas station on Atlantic just west of I-95.”

“Okay, I'll be there in a bit.”

Half an hour later, I arrive at the gas station to find Spring sitting next to a young man. “This is Josh,” said Spring, “and since we're doing all this driving anyway, could we drop him off at the West Palm Beach Tri-Rail station?”

“Sure,” I said. “I don't mind.” Josh and Spring got into the car and we drove off.

During the drive up to the West Palm Beach Tri-Rail station Josh was very quiet, only answering direct questions and not offering much else in the way of conversation. After dropping him off I asked Spring what exactly his story was, since he didn't really volunteer anything on the drive up, and she said he had walked from Key West to that gas station over the past three weeks, and that he was getting a bus ticket (courtesy of a friend) at the West Palm Beach Tri-Rail station for a cross-country trip to Sacramento, California for his mother's funeral.

Oh.

Okay then.

And that's all the details we have. No indication of how he ended up in Key West (apparently he's from Sacramento). Nor how he ended up sans transportation other than his two feet and other than that … not much else to say.

Friday, March 02, 2007

Two things

Two things, tangentially related, but enough to push me into a bad mood (it was the inability to log into a server that pushed me into a really foul mood, but I'm better now).

Thing the First: I'm driving about and I end up behind a school bus dumping kids off. Annoying, but a normal part of traffic at that time of day. No, what set me off was the line of cars along the side of the road waiting to pick up the kids. What? Can't let Brandyn and Heathyr walk a two blocks home, can we? (And for the record, the neighborhood was far from being South Central Los Angeles) Can't even be bothered to drive the few miles to the school to pick up Brandyn and Heathyr either. For those parents, I would love to give their kids their very own lawn roller coaster.

Have fun, kids.

Thing the Second: From a ticket in our trouble ticket system, “Is it possible foward a copy of an employees mail to another account temporarily without their knowledge?” What's wrong? Don't trust your employees? Need to watch over them like little kids? Perhaps you should give them their own lawn roller coaster too? But don't expect your employees to trust you much. (To be fair, I don't know the reason behind the request and there could very well be a legitimate reason, like a police investigation behind this, but this is my first reaction to this).


So what exactly is the point of dynamic libraries if the applications behave as if statically compiled? Could it be that the OpenSSH boys are too paranoid? Or just perpetuating a very cruel joke at our expense?

A few days ago Smirk received an updated security scan of a customer's box and they didn't like our version of OpenSSL (it being more than 20 minutes old, you see). Yesterday Smirk called and told me to update OpenSSL with the latest buggy version instead of the buggy version 30 minutes old.

In theory, it's easy enough. I mean, the whole point of shared libraries is that you can update just the library without having to recompile and relink a bazillion applications. So I download the latest version, compile and install. In checking over the programs that use SSL, it seemed just easier to reboot the box than to restart the bazillion processes (sorry Pinocchio). In theory, everything should just work.

In theory, there is no difference between theory and practice. In practice, there is.

Everthing came back up, except OpenSSH.

Sigh.

So today, at the office, I check into the problem. OpenSSH basically said, “Sorry, you're trying to use a version I wasnt' compiled against. Even though I'm dynamically linked against that library, I'm refusing to run. So Nyah!”

XXXXXXX piece of XXXX do as you're XXXXXXX told you XXXXXXXXXXXXX XXXXXXXXXX!

I was better.

Multiple attempts at recompiling later, it worked. Although I think I hurt my foot in the process …

[And I managed to botch the posting of this entry. Tells you how my day has been … ]

[TWICE! This got botched TWICE! And when I attempted to fix the problem, I ran into Linux's schizophrenic approach to the Backspace key. Hey Linus! It's XXXXXXX Ctrl-H you moron! ASCII value of 8! Eight! EIGHT! Not the XXXXXXX DEL character! BACKSPACE!

Bad Linus! No cookie for you!

And to further continue my downward spiral I clicked somewhere on Firefox and I lost the nagivation toolbar.

Hate hate hate hate hate hate hate.]


Speechless

Finally, a toy that invites children to explore the nature of cruelty. In fact, Electronic Test Tube Aliens ($15) are either the most cynical and ill-conceived toys on the market, or the world's first truly existential toy. The story is simple: There's an alien invasion on, and you get to be a collaborator by taking care of a Wi-Fi-enabled, battery-powered alien adoptee. Three of the aliens are good and three are evil; whether yours is good or evil has no bearing on how your creature will behave, since these test-tube babies can't fight each other or really do anything. Except die. In fact, that's their specialty.

Via Postcards from the Bleeding Edge, Tes t Tube Aliens: Gadget of the Week

You know … this just … fifteen dollars … words … fail me.

Next thing you'll know, peopl e will be selling virtual 70s style porn beds … oh wait a second …

Saturday, March 03, 2007

More Wiki than a Wiki

I've played around with several WikiWikiWebs (like TwikiK, which I find somewhat clunky, and UseModWiki, which I find okay) but none so far has impressed me more than TiddlyWiki, which has to be the easiest wiki to install—just one file and no web server required.

On the downside, it's just one file and I mean, everything is stored in that one file. It makes the editing of content pretty sweet and rather fast, but I'm guessing that as more content is added, the slower it gets since it all runs in the browser. An interesting twist might be to update content on the server using AJAX, although I'll have to check to see if it's already been done.

Sunday, March 04, 2007

First impressions of TiddlyWiki

I was initially very impressed with TiddlyWiki, but the more I play around with it, and think on how it works, the less inclined I am to actually use it.

I have a directory on my home computer called writings, which contains a ton of files related to writing. Ideas, notes and several attempts at novels (mostly attempted during National Novel Writing Month) litter the directory, making about 16 megabytes of stuff just sitting there, waiting for me to do something with it all (hmmm … a recipes file—interesting).

Sixteen megabytes. That's a large amount of text to store in a single file (aside from the issue of actually getting it all into any type of Wiki to begin with), much less work with a file that large. I did, however, import (using cut-n-paste) one of the files, ideas into TiddlyWiki to get an idea of what it would be like.

I'm resistant. I find it just as easy to use simple text files as it is to use TiddlyWiki, but with the text files, I can use any computer with Internet access and an ssh client. With TiddlyWiki, I would have to copy the file to whereever I am and afterwards, make sure to copy it back to my home computer (and yes, that is an issue with me).

There's also the sad fact that the base TiddlyWiki is over 220,000 bytes of JavaScript code and requires a 28MB “helper app” to execute whereas the editor I use is about 174,000 bytes, has more features (like the editing keys I have on my keyboard actually usable for their intended purposes), and doesn't require a multimegabyte “helper app” to execute (unless you count the operating system as a “helper app”).

I'm still looking for the perfect editing system.

Monday, March 05, 2007

Paralysis in the sleep

I think I finally figured out what triggers my sleep paralysis attacksnaps.

I ended up taking a nap this evening (combination of a really screwed up sleeping schedule and sleep depravation since I had to get up early today since P. is out of town), and I intended to only sleep for maybe an hour or so, but I slept longer than I expected. Durring the nap, I experienced an attack of sleep paralysis. It wasn't as bad as some of my previous attacks (now that I know what's going on, the process isn't nearly as frightening) but it still quite annoying and it seemingly takes forever to snap out of it.

But in thinking over my past attacks, they have all (to my recollection) happened when napping, or rather, napping longer than I wanted to nap.

Tuesday, March 06, 2007

“… in other news, pigs were seen flying by … ”

Since I no longer have to work at The Office, I brought home my workstation with the intent of using it to replace my aging home system linus.

processor	: 0
cpu		: 486
model		: Am5x86-WB
vendor_id	: AuthenticAMD
stepping	: E
fdiv_bug	: no
hlt_bug		: no
f00f_bug	: no
fpu		: yes
fpu_exception	: yes
cpuid		: yes
wp		: yes
flags		: fpu
bogomips	: 66.56

Yes, it's probably ten to twelve years old by now (in fact, I'm using it right now to write this very entry), and while still usable, it is getting a bit long in the tooth and now is as good a time as any to replace it.

The intent was to use my workstation to replace two computers (the aformentioned linus and my firewall, janet, a 33MHz 486) and a switch, since I have this four-port ethernet card.

After mucking about for a few hours today (and ripping my favorite shirt in the process—sigh), I've come to the conclusion that I can't replace the switch, since the four-port ethernet card doesn't work with modern Linux systems (in a weird twist of fate, it would probably work in the current linus since it's still running Linux 2.0.39—to say that the drivers for this card haven't been updated is an understatement—the card itself is over 13 years old). I was, however, able to munge up a 2GHz system with three network cards and an additional IDE controller (the intent here is to just dump the drives in linus into the new system, plus some other drives from some other computers around the house; I think I'll end up with six drives in the system).

While I'm not finished yet, I did however take the old drive out of tower, my first webserver and slapped it into my new computer. Odd seeing the state of the site from four years ago (back when Mark still had a blog), and hey, I can always use an additional 17G of space. Lord knows I paid enough for it.

Wednesday, March 07, 2007

“Good, bad, I'm the one with the compiler.”

I've been doing some heavy programming lately, dealing with schlepping bits into and out of QuickBooks (which I'll name Project “Pacino” which is related to the actual name of the project) and my part so far is with getting data into and out of MySQL.

The first pass involved writing an extention to MySQL to run an external program from a trigger. One guy, however, kept popping up on the various threads advising against this:

I always recommend against doing things like this. Calling an external processes from a trigger or UDF is very difficult to get right, and it is very easy to cause serious problems with your application.

Catch-22 of the Active Database

Well … good, bad, I'm the guy with the compiler. And Bill Karwin's advice of polling the database doesn't sit well with me. Heck, polling in general doesn't sit well with me (“Are we there yet?” “Are we there yet?” “Are we there yet?” “Are we there yet?” “Are we there yet?”). But I can see why Bill is cautious, and I wrote the code with his problems in mind.

It works, but there are cases when the notification doesn't go through (the program we invoke collects the updated record to update another, non- MySQL database (else we'd just use MySQL replication) and if we can't update the other database, the notification goes unnoticed). So it was back the drawing board for another approach. This time, the approach is for MySQL to log the changes to another table and to notify a daemon of the update. The daemon then pulls the changes from the table MySQL updated and does whatever with them. Since MySQL also logs the changes, if the daemon isn't running, the changes just pile up in a queue for later processing.

Now, as I'm working on attempt two, I did get permission to release the code for calling an external program from MySQL. The code is pretty simple and while it does work, it's quite simple (only MySQL strings are supported for instance) and could hammer a server pretty hard, depending upon the size of the update. It's not public yet, but if anyone were interested in the code, I can give it out …

Thursday, March 08, 2007

Scaling daemons

I'm still deep in programming.

So now I'm writing a daemon.

The first problem was getting MySQL to contact the daemon, and I forgot—I'm working under Unix, and interprocess communications suck under Unix. You have pipes, but they only work between processes that have a common ancestor. You can get around that problem by using named pipes, which get around the common ancestor, but there's still a limit to the amount of data that can be in the pipe, and if one side isn't listening (say, the daemon) then the other side is blocked. No good.

Oh, I could try using message queues. But it too, has problems—no automatic reclaimation of system resources when one side (or both!) crash. They're not identified by name and there are no tools to list the exiting message queues or delete them! And they can't be used with the multiplexing I/O API (select() or poll(), which I'll probably be using if I'm dealing with tons of connections).

The same problems exist for shared memory by the way, plus a whole slew of synchronization problems between unrelated processes, which probably mandates the use of semaphores, which again, have similar problems with message queues and shared memory.

Told you interprocess communication under Unix sucks.

Leaving sockets. Since they use regular file descriptors, they work with the multiplexed I/O API, but I hate using select(), since you end up scanning through arrays. The code that uses select() typically looks like:

while(1)
{
  FD_ZERO(&list);
  
  for (i = 0 ; i < files_count ; i++)
    FD_SET(files[i],&list);
  
  rc = select(FD_SETSIZE,&list,NULL,NULL,NULL);
  
  if (rc < 0)	/* select() returned an error */
  {
    handle_error(errno);
    continue;
  }
  else if (rc > 0)	/* we got some */
  {
    for (i = 0 ; i < files_count ; i++)
    {
      if (FD_ISSET(files[i],&list)
      {
        if (files[i] == listen_socket)
        {
          len = sizeof(remote_addr);
          connection = accept(listen_socket,&remote_addr,&len);
          
          /*----------------------------------
          ; oh great, we need to add this to the end
          ; of the files array, but that readjusts the 
          ; file_count variable ... buyer beware ... 
          ;-------------------------------------*/
          
          add_to_list(files,connection);
        }
        
        /*-----------------------------------
        ; oh bloody hell, we're listening to 
        ; MySQL as well ... sigh.
        ;----------------------------------*/
        
        else if (files[i] == mysql_connection)
        {
          handle_that_mess(mysql_connection);
        }
        
        /*---------------------------------------
        ; otherwise it's a connection from outside
        ;--------------------------------------*/
        
        else
        {
          /*-----------------------------------
	  ; oh man, we need to find the data
          ; associated with this connection, so
          ; that means another scan of some other
          ; list ... Aiiiiieeeeeeeeeeeeeeee!

I've been down this route before, and it resulted in some of the most convoluted code I've ever written. And looking at poll(), it doesn't appear much better.

I could get around using select() or poll() by creating a multithreaded or multiprocess application, but that's a whole new can of worms I'm opening up (deadlocks or race conditions anyone?) in addition to the problems I mentioned above about interprocess communication.

In looking around for a usable solution, I came across epoll, which is a new multiplexing I/O API in the newer Linux kernels. Reading over the documentation, it looks like you add file descriptors to an “epoll queue” (which itself is a file descriptor), then you call epoll_wait() which returns an array of file descriptors that are ready for reading or writing! It saves scanning through an entire list of file descriptors continuously asking “do you have data?”

What sold me was looking at the definition of the event structure:

typedef union epoll_data {
	void *ptr;
	int   fd;
	__uint32_t u32;
	__uint64_t u64;
} epoll_data_t;

struct epoll_event {
	__uint32_t events; /* Epoll events */
	epoll_data_t data; /* User data variable */
};

User data variable?

I get a pointer?

Associated with a file descriptor?

No way?!

Define a few structures with function pointers, and boom! The main loop now looks like:

void mainloop(int queue)
{
  struct epoll_event list[10];
  int                events;
  int                i;
  struct foo         data;

  while(1)
  {
    events = epoll_wait(queue,list,10,TIMEOUT);
    if (events < 0)
      continue;	/* error, but we ignore for now */
    for (i = 0 ; i < events ; i++)
    {
      data = list[i].data.ptr;
      (*data->fn)(&list[i]);	/* call our function */
    }
  }
}

Man, this now becomes easy. No more having to constantly check file descriptors or maintaining lists of file descriptors. I'm in heaven with this stuff. Even better that this method scales beautifully.

Friday, March 09, 2007

Cheating your way to a robust daemon

Programs written in Erlang have minimal (if any) error checking. The intent by the designers of Erlang is for buggy Erlang code to crash early and hard. No defensive programming for these guys, which seems odd given that Erlang is used primarily in phone switches, which have ridiculous uptime and reliability requirements, but not really.

You see, most Erlang programs are watched over by an even simpler program that simply waits for a crashing program and restarts it automatically, while logging the incident.

It's a pretty neat concept, and for the daemon I'm writing, I've done just that.

Well, I don't actually have a separate process watching, because one isn't needed. No, what I've done is catch a few signals that end up killing the program (like SIGSEGV) and instead of terminating the program, restarting it.

extern char **environ;
char         *global_argv[];

int main(int argc,char *argv[])
{
  /*----------------------------------
  ; save our command line.  I do this
  ; so *if* we re-exec ourselves, we
  ; re-exec ourselves as we were initially
  ; exec'ed.
  ;----------------------------------*/

  global_argv = argv;

  /*--------------------------------------
  ; Wrote my own signal() function that ensures
  ; reliable signal semantics (via W. Richard Stevens'
  ; Advanced Programming in the UNIX Environment).
  ; 
  ; Here, I'm capturing those signals that
  ; may be the result of bad programming and
  ; end up generating a core file, and catching
  ; those to restart the program.
  ;----------------------------------------*/

  set_signal(SIGSEGV,crash_recovery);
  set_signal(SIGBUS, crash_recovery);
  set_signal(SIGFPE, crash_recovery);

  /* ... */

  return(EXIT_SUCCESS);
}

void crash_recovery(int sig)
{
  syslog(LOG_ERR,"received sig %d---restarting",sig);

  /*--------------------------------------------
  ; The signal we're handling may very well be
  ; blocked, which will persist across the execve()
  ; call.  This results in the first crash being
  ; caught, but not subsequent crashes.  By unblocking
  ; all signals, we assue we can catch further
  ; crashes.
  ;----------------------------------------------*/

  sigfillset(&sigset);
  sigprocmask(SIG_UNBLOCK,&sigset,NULL);

  /*---------------------------------------
  ; close all the files, but keep the standard
  ; STDIN, STDOUT and STDERR open.  Sure, we 
  ; loose any connections, but we'll loose them
  ; anyway if the program were to go away.  
  ;----------------------------------------*/

  for (i = 3 ; (i < OPEN_MAX) && (close(i) == 0) ; i++)
    ;

  /*---------------------------------------
  ; restart myself.
  ;------------------------------------*/

  execve(global_argv[0],global_argv,environ);

  /*----------------------------------
  ; well ... if we get here, we're screwed
  ; so might as well give up.
  ;------------------------------------*/

  _exit(EXIT_FAILURE);
}

This could be a very bad idea but I'll see how well it works out.

Saturday, March 10, 2007

Page views

I came across Project Wonderful from Eric Burns. I read up on its advertising scheme and found it rather compelling. I have web space to sell ads, and given that Google's AdSense has been a disappointment, I thought I would sign up and give Project Wonderful a try.

I'll have to wait a while.

In trying to keep the system from imploding under heavy traffic, they're slowly expanding and I have to sign up for an invite to display their advertising. On the form asking for the invite, they asked for an average number of page views per day my site gets.

I don't have a package like AWStats, Webalizer or Analog installed (being too lazy to install and configure them). Instead, I have some home brewed programs that allow me to trawl through the log files manually (which for me gives me a better feel for what's going on anyway). I figured just searching for screen.css would give a good indication of page views (since it's used to render a page view), so I extracted the logs from a few days ago and checked.

Thirty-seven page views.

That's it?

I tried another day.

Thirty-seven.

I went back to the January logs.

Thirty-seven.

Thirty-eight.

Sixty-four.

Thirty-eight.

Oh.

That might explain the rather lackluster results from Google's AdSense.

But in going through the logs, I did come across the following:

Plus other feed readers that don't report the number of readers (about another 70) so my readership is up there, but primarily through outlets other than here.

Well then … perhaps I have to rethink the whole advertising thing then.


Whose bright idea was that design?

If anyone is wondering why: PHP's strpos() returns “false” when the second string argument does not occur as a substring of the first argument, and returns 0 when the second string argument occurs at position 0 of the first string argument. Thus, strpos( “/admin”, “/admin” ) returns 0, but strpos( “Cabbage/admin”, “/admin” ) will return a positive integer.

You're supposed to test the return value explicitly: “if( strpos( $a, $b ) !== false)”, but it only says that like five times in giant red letters on the manual page (http://us2.php.net/strpos) so it's easy to see how someone could miss it.

Re: Cabbage Based Authentication

Besides being reason #3.1415926 for hating PHP, this is a further example of my dislike for dynamically typed languages (and muddled thinking). What we have here is a function that returns a positive integer if we find one string within another, but a boolean otherwise. This mixing of return types is futher compounded by the fact that in PHP, an integer value of 0 is also treated as the boolean “false” value.

So let's not fix strpos() to return something sane, like -1 for “string not found,” let's instead extend the langauge with a silly “boolean only comparison” to fix this particular problem.

I would really love to know what Rasmus Lerdorf was smoking


Science in action II

Bunny received one of those forwarded emails that detailed a bunch of stupid cell phone tricks one could try. Among the stupid cell phone tricks (like dialing “*#06#” to get the phone's serial number, or dialing 800-FREE-411 (800-373-3411) for free dialing assistance) was one really silly bit:

Subject: Have you locked your keys in the car?

If your car has a remote keyless entry device this may come in handy someday. If you lock your keys in the car and your spare keys and spare remote keyless device are at home, call someone at home from your cell phone, hold your cell phone about a foot from your car door, and have the person at your home hold your spare remote keyless device up to the phone and tell them to press the unlock button. Presto, your car will unlock. Saves someone from having to drive your keys to you. Distance is no object. You could be hundreds of miles away. All you have to do is reach someone who has the other “remote” for your car and you will be able to unlock the doors or the trunk (where it might be a good idea to keep a spare set of keys in case you lose yours).

Another remote frob myth that sounded way too silly to me.

So of course I had to try it.

I gave Bunny my keys and went outside to stand next to my car. Then I called her. “Help, help, I locked myself out of my car,” I said.

“Okay,” she said. “Don't panic. I have your spare set of keys right here in the house. Hold your phone about a foot away from the car.”

I did that. Nothing.

We tried again.

Nothing.

Bunny then suggested using her landline to call me. Perhaps it would give a better signal.

Nope.

I suspect it doesn't work since my keyless frob works on radio waves, not an actual audible sound.

[Busted]

Sunday, March 11, 2007

Home alone (with a few cats though)

Spring and Wlofie are away for the week, gone camping at Gulf Wars, an SCA event.

Me? I'm not the camping type; roughing it is a hotel room with spotty Internet access.

Here's hoping they have fun.


As you wish.

Computers excel at following instructions to the letter.

Programmers don't quite excell at giving instructions to the computer.

Case in point: the daemon I'm working on. Through testing, I found that the automatic restarting wasn't working in all cases. If the program ran in the foreground, it would restart properly upon a crash. If it started up at an actual daemon though, it would fail. It took me a few hours to debug the problem, primarily because for this problem, I couldn't use gdb (the Unix debugger) for a few reasons:

  1. going into daemon mode creates a new process, which isn't the one that gdb starts debugging. To get around that problem, you can start the program up, and then attach gdb to the running process. That still leaves
  2. gdb will catch the segfault for you, instead of passing it on to the program. There very well may be a way to pass it on, but I'm not sure how well gdb handles signal handlers.

Painful as it is, the lack of a debugger can be worked around. And before I reveal the actual problem, here's the relevant code (sans error checking, as that only clutters things up):

int main(int argc,char *argv[])
{
  global_argv = argv;	/* save argument list for later restarting */

  if (gf_run_in_foreground == 0) 
    daemon_init();

  signal(SIGSEGV,crash_recovery);
  
  /* rest of program */
}

void daemon_init(void)
{
  pid_t pid;

  pid = fork();
  if (pid == 0)		/* parent exits, child process continues on */
    exit(EXIT_SUCCESS);

  chdir("/tmp");	/* safe place to execute from */
  setsid();		/* become a session leader */
  close(STDERR_FILENO);	/* close these, we don't need them */
  close(STDOUT_FILENO);
  close(STDIN_FILENO);
}

void crash_recovery(int sig)
{
  extern char **environ;
  sigse_t       sigset;

  syslog(LOG_ERR,"restarting program");

  /*---------------------------------
  ; unblock any blocked signals,
  ; including the one we're handling
  ;---------------------------------*/

  sigfillset(&sigset);
  sigprocmask(SIG_UNBLOCK,&sigset,NULL);

  /*---------------------------------
  ; restart ourselves.  If the call
  ; to execve() fails, there's not 
  ; much else to do but exit.
  ;---------------------------------*/

  execve(global_argv[0],global_argv,environ);
  _exit(EXIT_FAILURE);
}

Another bit of critical information: I would start the program thusly:

GenericUnixPrompt> ./obj/daemon

If you're good (say, the calibre of Mark) you'll see the problem. If not, don't worry—it took me a few hours. Here's a hint: Once I removed the call to chdir(), the code worked fine in daemon mode, and no, chdir() wasn't failing.

In fact, it didn't matter where I put the chdir() call, having it in there would cause the re-exec to fail when running in daemon mode.

The problem?

By changing directories, the relative path I was using to start the program was no longer valid when calling execve(), and of all the places where I could check the return code, that wasn't one of them. It didn't dawn on me (until thinking about it for a while after removing the call to chdir()) what the actual problem was.

Sheesh.

Here was the program, doing exactly what I told it to do, only I didn't realized what I was telling it to do wasn't what I thought I was telling it to do.

My brain hurts.

As a postscript to this, even if I were able to start the program under gdb, trace into the new process created, pass on the segfault to the signal handler, it wouldn't reveal the problem because gdb uses the full path to the program when running it, thus masking the real problem.

Lovely, huh?

Monday, March 12, 2007

Steampunk Star Wars

This is for Jeff Cuscutis, who likes this sort of thing:

Massive Solar-Orbiting Electro-Mechanical Analytic Engine, Mark 6

This enormous Imperial space station, the size of a small moon or asteroid, is in fact an immense analytic engine, a device capable of making millions of calculations every day. Inside is kilometer after kilometer of tubes and wheels, cranks and gears, all spinning and clacking, spitting out an endless series of numbers for the Imperials scientists to decipher.

Via kisrael.com, E ric's Terrible, Horrible, No Good, Very Bad Idea: steampunk star wars

And the accompanying pictures are cool too (secret message to Jeff: can I get a Phlogisticated Aether Torch?).


Premature optimization

“We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%.”

Donald Knuth

Since when did correct data typing in the production database become optimizations???

Comments on We'll Optimize Later

This is echoing a feeling I've had now for the past year or so—the phrase “premature optimization is the root of all evil” has been so drilled into programmers that it seems like no thought at all is being employed.

Technically speaking, writing code is “premature optimization.” Why bother even writing code when we can call upon the mighty powers of the lazy web to see if it's been written already. Or something close. Heck, it doesn't even have to be close, as long as it's code that can be adapted (just try to ignore the time factor when it takes longer to adapt code than it would have taken to write code from scratch, which may make a better impedance match to the rest of your code).

So remember, thinking about your code is a form of premature optimization.


Hammers and nails

Before I started at The Company, Smirk used a spread sheet to keep track of IP address allocations. It was easy to set up and edit and it worked for him. Besides, he has it running anyway to help manage the finances of The Company. So why not use it?

Then I took on the job of allocating IP addresses. I used (and still use) text files (one for each Class-C block we use). It was easy to set up and edit and it works for me. In fact, I use text files extensively to keep track of all sorts of things at The Office, from firewalls to managed power strips.

When P started, he set up Twiki as the company knowledge base. I don't know how easy it was to set up, but P seems to find it adequate to use and is currently a bit upset that he's the only one who bothers to update it. I personally don't find it that easy to use and consequently, I don't use it.

Personally, I'm picky about editors, and while I can't say I love joe, I am comfortable using it. But heck, I'd rather use Emacs to edit than the crap editor you get in your web browser du jour (and yes, that includes Firefox). That partly explains why I dislike the Twiki (there are other reasons), and don't even use my own web interface to post entries here (it's almost exclusively the email interface).

The problem here is, all three of us use different tools to manage certain types of information about The Company, and because of that, we don't have a true company wide information base that we can rely upon.

And no one has an idea of what we should use, because of how we all work.

Tuesday, March 13, 2007

Those ol' collaborative blues

The tone for today was cast in electronic stone when I wrote the following in a thread:

For me, it can't be purely web based, as I loathe editing text in a browser (really, the editing capabilities of a <TEXTAREA> sucks). It has to feel quick (it doesn't have to be quick) and it should be easy to create new nodes, notes, blobs or whatever. I would like the ability to customize the key bindings (Home goes to begining of a line, Ctrl-Home to the start of the document, etc).

Oh, and multiplatform (at a minimum, Linux and Mac OS). Given that, I would want hooks for loading and saving to throw the document into and out of some form of version control software (because I want the ability to edit the master copy reguardless of which computer I'm on, and yes, I do use multiple computers at multiple locations on a regular basis).

So far, nothing has beat logging into my home computer and using a text editor.

Me, in a thread on scheherazade in blue jeans—Clarification on mindmapping stuff

While the thread in question was about mind mapping software I see parallels with the current situation at work.

I think I have a handle on what I hate most about WikiWikiWebs: editing the pages. Each wiki has its own concept of markup (more or less) and it's markup that is supposedly easier to type than HTML. And certain typographical conventions are rather easier to use than HTML, like *asterisks* for strong emphasis or _underlines_ for plain emphasis.

Heck, mod_blog has a few things like that, for instance “---” for “&mdash;” (which makes a nice “—”) or even “``” (two backtics, which on most keyboards is in the upper left corner) gets translated to &ldquo; which gives the nice opening double quotes.

No, where it starts failing for me is in the structural markup. Weird rules like “lines that start with an asterisk denote an unordered list, to get nesting, nest the lines”

* one
* two
  * a
  * b
* three

Or was that “lines that start with an asterisk denote an unordered list, get nest nesting, add asterisks”

* one
* two
** a
** b
* three

And was it a dash that started headers, or a percent sign? And what if you can't use the Tab key because the browser uses it to switch focus to other form elements? So you may have problems with wiki-formatting and editing under the browser.

Which leads us to actually editing text under a web browser, which I contend, sucks. Part of this is the browser, which has other ideas about the Tab key, and part of this is the operating system, which has its own ideas about what keys do what (like the Mac OS's concept of the Home key, and my concept of the Home key, are at odds).

From
"P" <XXXXXXXXXXXXXXXXX>
To
"Sean Conner" <spc@XXXXXXXXXXX> (email @ work)
Subject
Re: collaboration issues
Date
Tue, 13 Mar 2007 11:57:36 -0400 (EDT)

Sean,

Here a line from shell script I'm using to keep the site lists updated automatically. Basically just a post using wget (make sure your using a up to date version of wget).

wget -O /dev/null \
	--http-user=AutoUpdate \
	--http-passwd=XXXXXXXXXXXXX \
	--post-file=$tmp/sitelist \
	http://XXXXXXXXXXXXXXXXX/twiki/bin/save/$web/$topic

You may also find the following features useful.

-P

I looked, but wasn't overly impressed (unlike my reaction to TiddlyWiki) and I'm not a fan of WYSIWYG editors (P installed one on the Twiki) but as I replied to P, I'm not all criticisms with no suggestions—I did place all my work notes (and work related files) under a webserver on my workstation, to make it easier to get to them (even if they're a bit disorganized under names that may only have meaning to me) and write a webpage to display the current IP address allocations (which uses XMLHttpRequest() to fetch the text file and generates a table view—my ultimate intent is to allow one to edit the data using the webpage and have it update the file back on my workstation).

I also started looking at various Firefox extentions to hopefully make editing under Firefox a bit more tolerable. I ended up wasting a few hours removing and reinstalling Firefox because some editing extension (sorry, I don't remember which one I found the link in a text file of all things) screwed up Firefox (by adding a large amount of blank space to the bottom of the Firefox window, which I couldn't get rid of).

And if you think I'm making a mountain out of an anthill, I'm not. This issue is currently demoralizing everyone in the company (at the very least, I'm getting demoralized) and we at The Company need to find a solution to allows us to collaborate, now that we've gone all Virtual Office.

Wednesday, March 14, 2007

“Orange you glad I didn't say ‘daemon?’”

At The Company Weekly Meeting it was decided that I should stop work on the daemon I'm writing as we have a better way of doing what we're doing (no longer are we trying to get MySQL to notify an external application of updates). I'm not upset at the loss of the work I've done so far since going in I knew this was exploratory programming and thus subject to change.

In other news, Smirk was impressed with the webpage I set up to view IP address allocations, but as all too often with quick written hacks, it too is saddled with feature requests as it lurches its way towards being a major application (in this case, Smirk asked for half a dozen changes, some easy, some not so easy).

Looks like I'll be learning even more JavaScript now.

Thursday, March 15, 2007

Hammers, screwdrivers, wrenches and paperclips

From
"Smirk" <{{charles@pickint.net}}>
To
spc@{{pick.net}} (email @ work)
Subject
ip address stuff
Date
Wed, 14 Mar 2007 16:41:49 -0400 (EDT)

Hi Sean,

I like the IP address layout you are using. Could you add some features?

The check box column should have one checkbox in the column header that would toggle all other checkboxes on or off.

-S

I spent the day working on what I thought would be something quick.

The first order of business was to get the webpage (mentioned above by Smirk) to send the information it had back to the server. And that's when I started running into some real issues (and let me just state for the record that so far I'm not a fan of JavaScript). Issues with tool use (specifically, software tools) and user expectations.

The IP files I edit look something like this:

192.168.1.0	00:00:00:00:00:00	Obnoxico & Co. network
192.168.1.1	DE:CA:FE:BA:D0:01	managed switch
192.168.1.2		|		their stuff ... 
192.168.1.3		|
192.168.1.4		|
192.168.1.5		|
192.168.1.6		|
192.168.1.7	FF:FF:FF:FF:FF:FF	Obnoxico & Co broadcast

Nice and easy to read. Vertical columns nicely arranged. But each column isn't nicely delineated in the actual “text.” Here, let me do a “reveal codes” and I'll show you:

192.168.1.0→00:00:00:00:00:00→Obnoxico & Co. network↵
192.168.1.1→DE:CA:FE:BA:D0:01→managed switch↵
192.168.1.2→→|→→their stuff ... ↵
192.168.1.3→→|↵
192.168.1.4→→|↵
192.168.1.5→→|↵
192.168.1.6→→|↵
192.168.1.7→FF:FF:FF:FF:FF:FF→Obnoxico & Co broadcast↵

The right arrows (→) represent the HT character, and the crooked arrow (↵) represents the end of line marker (under Unix, this is a single character LF whereas under Windows, this would be the two character sequence CR LF). And by using HT as a field separator, my columns don't line up logically (although visually, in my text editor, they do).

And that's an issue.

A hard issue.

Oh sure, most people can probably deal with a file that looks like:

192.168.1.0	00:00:00:00:00:00	Obnoxico & Co. network
192.168.1.1	DE:CA:FE:BA:D0:01	managed switch
192.168.1.2	|	their stuff ... 
192.168.1.3	|
192.168.1.4	|
192.168.1.5	|
192.168.1.6	|
192.168.1.7	FF:FF:FF:FF:FF:FF	Obnoxico & Co broadcast

But I can't. It would drive me up a wall. The solution would be to read in each line, expand the tabs to spaces, then pull out each field according to which character columns they're in. That would solve that problem, but it still leaves some other issues.

The last three features Smirk requested I woudn't say are necessarily hard to implement, but getting the user interface right is. Or at least, a user interface I would like (and that would be a minimum number of mouse clicks, because lord knows I don't want to have to check 32, 64 or even 128 individual check boxes to unassign a block of addresses—then again, I'd probably never use the web interface at all so that point might be moot). But what Smirk is asking for is an interface closer to how he works, which mimics a spread sheet (which I touched upon the other day).

And there's still the issue of just how much Smirk or P will update the IP list. My updating the lists hasn't been that much of an issue, and the only reason it's an issue now is the lack of updates to The Company Twiki. (what good is a knowledge base if no one bothers to update the knowledge?) And if the number of times it actually comes up that Smirk has to update the IP list is small, then perhaps writing this piece of software isn't really worth the effort (which is where I'm leaning).

On the other hand, this issue is deeper than just updating a list of IP addresses—at the core, it's a collaboration issue (even if right now it's just between Smirk, P and I) and the fact that Smirk uses hammers, I use screwdrivers and P uses a wrench. And all we have are paperclips (hmmm … that certainly came out of left field).


“undefined” vs. undefined

I had this bit of JavaScript code (never mind that I am compelled to add a semicolon to the end of each line when it isn't needed):

var lines = req.responseText.split("\n")
  
for (var i = 0 ; i < lines.length ; i++)
{
  var row = table.insertRow(-1)
  var fields = lines[i].split("\t")
  var cell;

  cell = row.insertCell(0)
  cell.textContent = fields[0]

  cell = row.insertCell(1)
  cell.textContent = fields[1]
  
  cell = row.insertCell(2)
  cell.textContent = fields[2]
}

I have a text file which I've just loaded. I break it into lines, and then each line into sub-fields, each separated by a tab (this is the format I keep my IP allocation files in), and then stuff the entire thing into a large table.

So, from a text file that looks like this (where I'm showing the actual tab and newline characters as arrows):

10.0.0.0→00:00:00:00:00:00→Backup network↵
10.0.0.1→DE:CA:FB:AD:00:01→mobybackup↵
10.0.0.2→DE:CA:FB:AD:00:02→dnsserver↵
10.0.0.3↵
10.0.0.4↵
10.0.0.5→DE:CA:FB:AD:00:03→mailserver↵
10.0.0.6↵

and I end up with something that looks like:

Sample output
IP MAC Notes
10.0.0.0 00:00:00:00:00:00 Backup network
10.0.0.1 DE:CA:FB:AD:00:01 mobybackup
10.0.0.2 DE:CA:FB:AD:00:02 dnsserver
10.0.0.3 undefined undefined
10.0.0.4 undefined undefined
10.0.0.5 DE:CA:FB:AD:00:03 mailserver
10.0.0.6 undefined undefined

The undefines pop out because there's nothing else to the line except an IP address, so fields[1] and fields[2] literally have nothing in them, not even the empty string. They are devoid of any value whatsoever.

Okay, fine, whatever.

Now, I go save what I have in the table back to the server. So I write some code:

var table = document.getElementById('tdisplay')
var textfile = ""

for (var i = 0 ; i < table.rows.length ; i++)
{
  var ip   = table.rows[i].cells[0].textContent
  var mac  = table.rows[i].cells[1].textContent
  var note = table.rows[i].cells[2].textContent
  
  textfile = textfile + ip + "\t" + mac + "\t" + note + "\n"
}

And what do I get back?

10.0.0.0→00:00:00:00:00:00→Backup network↵
10.0.0.1→DE:CA:FB:AD:00:01→mobybackup↵
10.0.0.2→DE:CA:FB:AD:00:02→dnsserver↵
10.0.0.3→undefined→undefined↵
10.0.0.4→undefined→undefined↵
10.0.0.5→DE:CA:FB:AD:00:03→mailserver↵
10.0.0.6→undefined→undefined↵

Oh wait! That's not what I wanted! Okay …

for (var i = 0 ; i < table.rows.length ; i++)
{
  var ip   = table.rows[i].cells[0].textContent
  var mac  = table.rows[i].cells[1].textContent
  var note = table.rows[i].cells[2].textContent

  if (!ip)   { ip   = "" }
  if (!mac)  { mac  = "" }
  if (!note) { note = "" }
  
  textfile = textfile + ip + "\t" + mac + "\t" + note + "\n"
}

And now let's see what I get:

10.0.0.0→00:00:00:00:00:00→Backup network↵
10.0.0.1→DE:CA:FB:AD:00:01→mobybackup↵
10.0.0.2→DE:CA:FB:AD:00:02→dnsserver↵
10.0.0.3→undefined→undefined↵
10.0.0.4→undefined→undefined↵
10.0.0.5→DE:CA:FB:AD:00:03→mailserver↵
10.0.0.6→undefined→undefined↵

Whoah! Wait! It looks like that doesn't work. Do some reading, oh, I need to use the “===” equality operator instead of the “==” equality operator (shades of Lisp here).

for (var i = 0 ; i < table.rows.length ; i++)
{
  var ip   = table.rows[i].cells[0].textContent
  var mac  = table.rows[i].cells[1].textContent
  var note = table.rows[i].cells[2].textContent

  if (ip   === undefined) { ip   = "" }
  if (mac  === undefined) { mac  = "" }
  if (note === undefined) { note = "" }
  
  textfile = textfile + ip + "\t" + mac + "\t" + note + "\n"
}

And I get …

10.0.0.0→00:00:00:00:00:00→Backup network↵
10.0.0.1→DE:CA:FE:BA:D0:01→mobybackup↵
10.0.0.2→DE:CA:FE:BA:D0:02→dnsserver↵
10.0.0.3→undefined→undefined↵
10.0.0.4→undefined→undefined↵
10.0.0.5→DE:CA:FE:BA:D0:03→mailserver↵
10.0.0.6→undefined→undefined↵

That's not working? What's going on here?

Then a lightbulb goes on. The variable note isn't undefined, it's "undefined", as in, the string consisting of the letters u-n-d-e-f-i-n-e-d. I changed the code used to construct the table:

var lines = req.responseText.split("\n")
  
for (var i = 0 ; i < lines.length ; i++)
{
  var row = table.insertRow(-1)
  var fields = lines[i].split("\t")
  var cell;

  cell = row.insertCell(0)
  cell.textContent = (fields[0] !== undefined) ? fields[0] : ""

  cell = row.insertCell(1)
  cell.textContent = (fields[1] !== undefined) ? fields[1] : ""
  
  cell = row.insertCell(2)
  cell.textContent = (fields[2] !== undefined) ? fields[2] : ""
}

And I finally got what I was expecting:

10.0.0.0→00:00:00:00:00:00→Backup network↵
10.0.0.1→DE:CA:FE:BA:D0:01→mobybackup↵
10.0.0.2→DE:CA:FE:BA:D0:02→dnsserver↵
10.0.0.3→→↵
10.0.0.4→→↵
10.0.0.5→DE:CA:FE:BA:D0:03→mailserver↵
10.0.0.6→→↵

Now, I had originally written this as an indictment against dynamically typed languages, but really, it's not, now that I think about it. C can also have undefined variables, but they're usually pointers, and they usually contain NULL (less rarely, some other illegal address). I think my problem here was a mental mismatch with what was actually going on, which I'm finding is all too easy in a dynamically typed language like JavaScript. Was the variable undefined because it was actually undefined, or was it "undefined"?

Would using a statically typed language helped me here? Possibly. It might have forced the issue of “undefined” at compile time. Or possibly not (on my system, doing something like printf("%s\n",NULL) results in “(null)” being printed, which isn't catching the problem at compile time). But the hiding the issue (or in this case, not crashing) makes it harder to debug such things.

Friday, March 16, 2007

“Go away! We don't want you!”

I'm having to do some work on SugarCRM, and I just now noticed that the default installation has a robots.txt file:

User-agent: *
Disallow: /

As written, this will prevent the site from being indexed by the various search engines. I wonder how many people using SugarCRM are aware of this? Or even care? I couldn't find anything about it mentioned in the documentation, but I just did a cursory search.

Saturday, March 17, 2007

A memo to myself

Rethink ordering take-out from that Chinese restaurant.


The Emperor's New Security Detail

You're about to read a real-life heist story. Super Bowl XLI was a Level One national security event, usually reserved for Presidential inaugurations. We had to get two full vanloads of materials through federal marshals, Homeland Security agents, police, police dogs, bomb squads, ATF personnel, robots, and a five-ton state-of-the-art X-ray crane. It took four months and a dozen people to pull off the prank that ended up fooling the world.

This is the Super Stunt.

Via Jason Kottke, Super stunt: The most ambitious prank in history.

On the one hand, I think this is great that four guys were able to pull this off and to show just how silly excessive security really is. On the other hand, this is downright scary that four guys were able to pull this off at a Level One National Security Event. On the gripping hand, I hope the guys don't end up at Guantanamo Bay for pointing out the Emperor's President's new security detail.

Sunday, March 18, 2007

No longer home alone

Spring and Wlofie returned from Gulf Wars late tonight, tired, a bit grungy, and with a boat! How they ended up with a fairly modern small fishing boat at a Medieval re-enactment festival is just one of those questions I've learned not to ask.

I will say, however, that the cats are happy to have more worshippers humans about Casa New Jersey. Now, maybe they'll leave me alone.

Monday, March 19, 2007

Short day

It's a short day today, as I have to go to bed early in order to make it to the West Palm Beach County Courthouse for jury duty by 8:00 am.

Is the sun even up at that hour?

Ick.

Tuesday, March 20, 2007

Notes from a courthouse

I left Casa New Jersey about twenty minutes later than I wanted to, but I still made it to the West Palm Beach County Courthouse on time (well, a few minutes past 8:00 am, but I think they said 8:00 am to ensure everybody shows up by the real time of 9:00 am). Traffic was a bit hectic, and the instructions given had jurors parking about two miles south of the actual courthouse at the convention center.

From the convention center it was a short bus ride to the courthouse where all jurors (over 200) checked in and sat around waiting. After an introductory instructional film (which pegged a few hot buttons of mine, but more on that when I have time) I was immediately called as a potential juror, unlike the last time where I got called at the end of the day.

But like last time, I did get called to be an actual juror. After voir dire we got a lunch break and there is wi-fi at the court house—oops, gotta get back to court.


A message to someone

[Hippo]
[Birdy]
[Two ewes]

More on this later

I heard one half of the case today. At 5:30 the judge asked if we jurors wanted to go home, or continue (only he took about ten minutes to explain that). It was fairly unanimous that we continue tomorrow.

I got home in time to head on out to dinner for a special occasion. I just now got home.

I'm tired.

I'm going to bed.


An unholy alliance if there ever was one

I'm going to bed but first, a link (via Flutterby) to a case going before the Surpreme Court that has both the ACLU and the American Center for Law and Justice (aka Pat Robertson) on the same side.

And what can unite these two forces behind the defendant?

Bong Hits 4 Jesus (and in the immortal words of Dave Barry, “I am not making this up”).

Wednesday, March 21, 2007

untitled

“Mr. Conner, is there any reason I shouldn't have you arrested?”

“No. No reason at all.”

Yes, that was my answer to a very furious judge. I can only suppose that such an answer to such a question was a very brave (or a very foolhardy) thing to do; the judge did not have me arrested for such a candid answer (much to my and the bailiff's relief).

So, how did I, on day two of jury duty, find myself standing in front of an irate judge ready to arrest me?

You see, it all started when I failed to set my alarm clock correctly. We were instructed by the judge to return today at 9:00 am. I thought I set my alarm clock for 7:00 am, but I missed one small little detail: 7:00 pm.

Sigh.

I woke up and noticed it being brighter than I expected. I took a look at the clock—9:23 am.

XXXX!

Ten minutes later I was showered, dressed and putting on my shoes when I received a call from the West Palm Beach Courthouse asking where I was. I apologized profusely and said I was walking out the door.

The drive was stressful, hitting every light, stuck behind every slowpoke. I was almost to the I-95 on-ramp when I realized I forgot my jury badge.

XXXX!

It was one of those “damned if I do, damned if I don't” type decisions—do I need that badge? Will not having it be more trouble than being even later? I erred towards having it. That cost me quite a bit of time.

The traffic lights slowed me down.

So did the traffic.

And the rail road crossing with the non-existent train crossing.

It seems my karma got mauled by dogma. Or something like that.

By the time I arrived at the court room, it was 10:31 am.

Now, when the courthouse called, I was instructed to report directly to the courtroom. But when I got there an hour and a half late at 10:31 am there was no one outside. I cautiously entered to find the trial well under way.

As the bailiff led me to the benches in front of the court, the judge called a five minute recess, and then had the bailiff escort the jury to the jury room. After they left, he asked if all the jurors had been escorted out of the room. Um, I thought, aren't I a juror? I raised my hand and made some form of noise—

“Quiet,” said the judge. “I don't want to hear from you.” He leaned back. “No, not you,” he said, talking to the defendant. The courtroom was quiet for a minute. “Bailiff, please escort Mr. Conner to the podium.” Pause while I was escorted. Once there, the judge rattled off contempt of court charges, which included a month of jail time and fines, and would I like to explain what exactly happened?

After I spoke, well … that brings us up to the start of this entry.

The actual punishment dealt out to me by the judge was about as bad as internal detention one would get in high school. I had to go back to the Jury Assembly Room and sit there for the rest of day to reflect on my actions of this day.

And boy, did I reflect. I felt awful, having wasted not only the judge's time, but that of the defendant and other jurors (the lawyers, not so much since they're probably earning a few hundred bucks per hour). By the time I got to the Jury Assembly Room I was in tears.

Horrible experience. Although I did call my friend Hoade (using the Stupid Cell Phone Trick of dialing 800-FREE-411 to get his number. Talking to Hoade will always cheer me up.

But that's it. I technically served my time as a juror, and, given what happened today, I would be surprised to find myself called anytime soon.

Thursday, March 22, 2007

untitled II

Now, about that court case

Yesterday I ran into one of the jurors during lunch (oh, the judge wasn't that sadistic as to feed me only bread and water). Since the jury was removed from the courtroom before my dressing down, he was curious as to what exactly happened. So I told him what happened, and he told me that later on, the judge also dressed down one of the witnesses on the stand.

I can only surmise that the judge was having a bad hair day.

I also gave him my email and phone number so that I could get some closure to the case once it's over. This morning he called and gave that closure.

Now, since the case is over, I can talk about it. The defendant was charged with DUI, with a BAL of 0.12 (which does exceed the Florida legal limit of 0.08). During the trial, it came out that he was involved in a motocycle accident (he was driving the motocycle) and that his passenger, his wife, died in the accident. His blood was drawn as evidence two and a half hours after the accident, and by using a formula (I forgot the actual name, but it was something like “retrograde determinant” or something like that) his BAL at the time of the accident was between 0.14 and 0.17, twice the legal limit.

The testimony I heard was the State's side, and I missed the defendant's side of the story, but the State's evidence was strong and there was no way the alcohol in the defendant's blood could have risen after the accident.

He was found guilty.

Now, the full story (the juror researched the background after the trial—some of the following details did not make it to the courtroom). The accident happened on September 25th, 2005, on the defendant's birthday. He, and a bunch of friends had been bar hopping all day and were on their way to another bar when an alien (and I don't remember if the alien was illegal or not) hit the defendant, causing the accident (so it wasn't the defendant that caused the accident). The alien had been stopped four times previously for driving without a license. The defendant's wife died at the scene, but the defendant wasn't told this for three days (apparently he had extensive injuries, and in the courtroom he walked with a cane and a pronounced limp).

The juror I spoke with was upset at having to deliver a guilty verdict, but as per instruction by the judge, he was guilty of driving under the influence. And I really feel for the defendant.

He was only sentenced to twenty days in jail, though.

Friday, March 23, 2007

Hot buttons

The other day I mentioned the jury instructional film setting off a few hot buttons of mine, but I forgot about it until Bunny reminded me about it.

The first hot button—democracy. We are not a democracy. A democracy is two wolves and a lamb voting on what's for dinner. No, we are a representational republic with democratic leanings. That's where the two wolves and the lamb appoint representatives and the choice of dinner ends in deadlock, as it should be. But this is a minor gripe compared to the next one.

The other hot button that got pressed—“jury of your peers.” Yup, the film actually said “we have a right to a trial with a jury of your peers.”

No!

No, no, no, no, no, no, no, no, and no!

Article 3, § 2 of The Constitution of the United States (emphasis added):

The trial of all crimes, except in cases of impeachment, shall be by jury; and such trial shall be held in the state where the said crimes shall have been committed; but when not committed within any state, the trial shall be at such place or places as the Congress may by law have directed.

Amendment VI of the Constitution (emphasis added):

In all criminal prosecutions, the accused shall enjoy the right to a speedy and public trial, by an impartial jury of the state and district wherein the crime shall have been committed, which district shall have been previously ascertained by law, and to be informed of the nature and cause of the accusation; to be confronted with the witnesses against him; to have compulsory process for obtaining witnesses in his favor, and to have the assistance of counsel for his defense.

and Amendment VII of the Constitution (emphasis added):

In suits at common law, where the value in controversy shall exceed twenty dollars, the right of trial by jury shall be preserved, and no fact tried by a jury, shall be otherwise reexamined in any court of the United States, than according to the rules of the common law.

Do you see “peers” stated anywhere in the Constitution?

No.

Why do you not see “peers” stated in the Constitution?

Because we don't have a peerage system here in the United States, despite our legal system having largely derived from England.

Why do we not have a peerage system in the United States?

Because our Founding Fathers specifically rejected the peerage system.

I knew our educational system was bad, but this bad?

Sheesh!

Saturday, March 24, 2007

Da-da-da-duuuuummmmmmm!

As long as I'm not a party, I find arguments amusing. Once, when working at IBM I nearly laughed out loud during an argument that took place in a meeting (and got dressed down by my team leader—there's a reason why I don't have a real job).

I also find arguments fun to write—there's just something inherently silly about an argument when two people are arguing past each other. But I never thought to set an argument to Beethoven's Fifth Symphony (link via news from me), much less improvise it live on TV.

Sunday, March 25, 2007

A self-referential post demonstrating the lameness of meta blog humor

I hate blog posts that are nothing more than a note saying there's nothing to blog about.

Don't you?

Monday, March 26, 2007

Notes on what geeks find interesting

I've been using Linux for over twelve years now, and I'm still learning it.

Today, Wlofie and I spent a few hours doing Stupid Shell Tricks under Linux—stuff like naming files “ ‥ ” (that's space period period space or even “ . * & ! prang” (that's space period space asterisk space ampersand space explanation point space "prang") or even “-rf *”—names that give the Unix shell fits (or naive users fits trying to get rid of such files).

From there, we ventured into the territory that crackers use to hide their activities under Unix systems. One such trick is the following command:

GenericUnixPrompt> hacker_tool || rm -rf ./

Kill the running hacker_tool process and all the files are removed. A process listing will only show the hacker_tool running. A smart cracker will zap or munge the history file of the shell. So that's a pretty hard thing to detect.

Another trick a cracker will do to make things difficult is:

GenericUnixPrompt> hacker_tool &
[1] 4532
GenericUnixPrompt> /bin/rm hacker_tool

This starts the hacker_tool, then the executable is removed. The program still runs since the code is in memory, but there's no way to actually recover the executable.

Or so I thought.

Wlofie showed me this though (at least, under Linux):

GenericUnixRootPrompt# cd /proc/4532
GenericUnixRootPrompt# cp exe /tmp/recovered_executable_file
	# or alternatively
GenericUnixRootPrompt# dd if=exe of=/tmp/recovered_execuable_file

Ah, the things geeks find interesting.

Tuesday, March 27, 2007

“The tires will only last for about 15 minutes, but it's okay because the fuel runs out in 12 minutes.”

I've written about the Bugatti Veyron, the obscene 1,000Hp 8 liter W-16 production car that tops out at over 250mph (but at a price—a million for a car that gets only three miles per gallon).

But man, it certainly looks very fun to drive (via Jason Kottke).

Wednesday, March 28, 2007

“But, it goes to 11.”

Smirk has a theory that every ten days or so, things go crazy and it's difficult to cope with what's being thrown at you.

Today is a day ten (short version—no Internet at Casa New Jersey, which means no email (and the troubles in getting an alternative email server set up), and many pointless trips to a customer site trying to get a new router configured).

But, despite how bad my day was, it wasn't as bad as Spring's, who had to endure a company work reschedule, a late train, and is now stuck in Atlanta due to a cancelled flight (she's on her way to visit The Kids in Colorado), and that's just the not so bad things that happened.


Virtually working

So, like, if Casa New Jersey has no Internet, how can I post?

I'm staying at Bunny's house. And for the next few days I'll be working from Bunny's house. Given that The Office has gone all virtual (oh yes, a few months ago actually—it's great working mostly from home and it saves a ton of money on gas), what with VoIP phones and what not, I can really work from anywhere that has an Internet connection.

And I finally got my email situation worked out.

Thursday, March 29, 2007

“Scotty, Mi devas deform rapido en tri minutoj aŭ ni ĉiuj estas mortinta!”

William Shatner is William Shatner, even in Esperanto.


“Remember, we're all in this together.”

Brazil, 1985, directed by Terry Gilliam, written by Terry Gilliam, Charles McKeown, and Tom Stoppard. In Brazil, Terry Gilliam asks the audience to imagine a world where the government wages a never- ending war with shadowy terrorists, a world where civil liberties are being destroyed in the name of security, a world where torture becomes official state policy in order to conduct more efficient interrogations of suspected terrorists. What's more, in Gilliam's fictional world, the central government is not just secretive but incompetent. Mistakes are made, leading to the imprisonment and torture of innocents. Most offensive of all, Gilliam implies that such a government could exist without its citizens staging an armed revolt. I'm usually willing to suspend disbelief, but this goes too entirely too far.

Via Jason Kottke, #51: Brazil

Yeah, he's right—a government like that could never happen.


I'm ambivilent about network neutrality

I've been wanting to write this for a few months now (and the orginal intent was to write it for the other site but I'm not sure if Smirk would agree with me) but since Jason Kottke linked to Craig “Craigslist.org” Newmark's article on the subject, I figured it was time.

Net neutrality.

Should the network be neutral in the traffic it transports, or can it prioritize the data depending upon content, destination, or both? It's an argument with proponents on both sides of the issue and it pretty much breaks down into individuals and small companies wanting neutrality, while the large multinational corporations want to shape the traffic.

Me?

I personally would like to see a neutral Internet, but I also see no problem with companies doing what they want to network traffic they carry. What I don't want to see is government regulation of what can and can't be done on the Internet. And generally, I feel the whole movement is moot anyway, because the net will always be neutral.

How?

Economic, my dear Watson.

Data is transfered across the Internet using the Internet Protocol, IP. To transfer a file, it's broken up into small bundles of data called packets, wrapped with a source address (where it's coming from) and a destination address (where it's going to), and pumped out through some piece of hardware (an Ethernet card, USB, serial line, T-1, OC-3, heck, IP packets can even be transported using avian carriers) to another device that's closer to the destination. That device then takes the packet, looks at the destination address, and pumps the packet out some hardware port to another device that's closer, and the process repeats until the destination is reached, on average, in less than 20 such hops [1].

Now, the closer to the “core” you get, the more packets a router (a dedicated device to sling packets around) has to handle. To this end, most routers have hardware dedicated to slinging the packets around, and since the destination address is at a fixed point on the IP packet, it's easy (relatively speaking) to make dedicated hardware for this function. And it's important this be fast, because a core router may be handing 50,000 packets a second (the router The Company's traffic flows through handles about 4,000 packets a second) and comparing each destination address against a routing table with perhaps 200,000 possible destinations. Assuming a binary search on the routing table, that's 17 comparisons on average per packet (18 max), times 50,000 packets per second, or 850,000 comparisons per second, or about one comparison per µsecond [2].

But the second other criteria are added to the routing entries, fewer packets can be processed on a given router. Say you want certain source addresses to be routed over faster links. Now, not only do you have to scan the destination address, but the source address as well. But the dedicated hardware in routers are only there for scanning destination addresses—scanning other parts of the packet require the CPU in the router to handle the packet.

Ouch.

And scanning deeper into the IP packet, say, for a TCP port (like TCP port 80, which is the default port HTTP runs over) requires some additional processing to locate the TCP header, since the IP header is variable in length.

Ouch.

And then there's the administrative overhead.

Oh yes, maintaining a list of “fast addresses” (say, to partnering networks) isn't free. There's overhead in maintaining the list. There's overhead in distributing the list to all the routers across a network. There's overhead in troubleshooting: “Why did the packets go there?”—a few hours later—“So, which is more important, streaming video from Viacom to AT&T or VoIP from AT&T to Verizon?”—a few days later—“But if we do that, that impacts the data from Sprint, who just signed a major deal with us.”

Ouch.

And my example there assumes that AT&T hasn't already bought Verizon. Heck, in these days of multinational mergers it's hard to know who owns what; just the politics of running a non-neutral network is mind-boggling to me, never mind the technical aspects of it.

A simple network is cheaper to run. A simple network is faster too.

Cheaper to run. Faster. Higher profit margin. I would think this would be a no brainer.

Oh, and did I mention that the current version of IP, which was designed over thirty years ago, has a field for “Quality of Service” which is rarely, if ever, actually used? Why? A few reasons:

  1. The most commonly used network API, the one from BSD Unix, never had a way for applications to set this field.
  2. It slows down a router (see above).
  3. It's an administrative nightmare. Heck, BGP, a routing protocol between networks, is an administrative nightmare and that's just dealing with destination addresses—it doesn't deal with quality of services at all.
  4. There's no guarentee that the network you send traffic to even supports “Quality of Service.”

It's been found over and over again that it's cheaper and easier to make faster routers than to implement quality of service across the network.

So I'm of the opinion—let the big boys waste their money on smart networks. Let them learn the hard way that a stupid network is, in the long term, better.

And that's why I'm not really concerned about network neutrality. The market will sort it out.

  1. I tried finding an actual number for the average number of hops across the Internet but the only numbers I could find (about 15) were for 1999–2000 with nothing more recent. Given the growth since then, I'll play it safe and say the average is no more than 20. [back]
  2. And it wouldn't surprise me if I'm underestimating the number of packets per second by an order of magnitude. [back]

Update on Friday, March 30th, 2007

Added a link to Wikipedia, and a small addendum to this entry.

Friday, March 30, 2007

Still ambivilent about network neutrality

I read up on net neutrality on the Wikipedia and while I learned quite a bit that I didn't know (like “quality of service” is more prevalent that I expected) it still didn't change my feelings towards the issue, but it's still worth reading.

Saturday, March 31, 2007

Incommunicado

Well, we still don't have Internet access at Casa New Jersey, so new entries may be spotty over the next few days until connectivity is restored.

You have been warned.

Sunday, April 01, 2007

Emergency Posting System

This is a test of the Emergency Posting System.

[Emergency Posting System]

This is a test of the Emergency Posting System. The bloggers of your area in voluntary cooperation with federal, state and local authorities have developed this system to keep you informed in the event of a lack of posts. If this had been an actual post, the Attention Signal you just saw would have been followed by official information, news or instructions.

This concludes this test of the Emergency Posting System.

Monday, April 02, 2007

Notes on the Emergency Posting System

It's nice to see that the Emergency Posting System worked as intended, but there did seem to be some problems with the color yesterday. No idea why …

Tuesday, April 03, 2007

A few thoughts for the day

In theory, there is no difference between theory and reality. In reality, there is.

No plan survives first contact with the enemy.

Never ask a technician how long it will take to fix something. Someone else has already asked, you'll blow the technician's concentration, and it'll then take twice as long to fix.

Wednesday, April 04, 2007

Just a little thought about digital video recorders and advertising

Bunny's had a DVR for a couple of months now, and it's gotten to the point where watching live TV is annoying, especially because of the “30-second fast-forward” button (press it, it goes fast-forward through 30 seconds worth of video). It's not an immedate jump—no, it actually fast forwards.

Now, I'm amazed that advertisers haven't attempted to make a commercial that's watchable when fast-forwarding. I timed the “30-second fast-forward” button, and it takes 3 seconds to skip forward 30 seconds of video. 10-to-1 compression. Okay, what can one do in just three seconds?

What can one do in ten seconds? (for the record, I heard about that contest over a year ago) I came up with a few ideas that had an actual narrative structure, and just a few days ago, I realized I could probably do an entire Ernest Hemingway short story in 10 seconds. Three seconds is more than enough for brand building.

It's just a matter of time before some advertiser tries this.

Thursday, April 05, 2007

Entry Interrupted

Still without Internet access at Casa New Jersey (although that may be resolved in the next day or two). In the mean time, work has been keeping me busy.

Fir—

Update on Friday, April 6th, 2007

Wouldn't you know it—a power outtage when writing this entry. I have no idea where I was going with this entry.

Sigh.

Friday, April 06, 2007

And you thought you owned your computer

The Vista Content Protection specification could very well constitute the longest suicide note in history.

A Cost Analysis of Windows Vista Content Protection

And it only gets better from there. Some choice quotes:

Since the S/PDIF link to your amplifier/speakers is regarded as insecure for playing the SA content, Vista would disable it, and you'd end up hearing a performance by Marcel Marceau instead of Pink Floyd.

A Cost Analysis of Windows Vista Content Protection

Amusingly, the Vista content protection docs say that it'll be left to graphics chip manufacturers to differentiate their product based on (deliberately degraded) video quality. This seems a bit like breaking the legs of Olympic athletes and then rating them based on how fast they can hobble on crutches.

A Cost Analysis of Windows Vista Content Protection

The Microsoft specs say that only display devices with more than 520K pixels will have their images degraded (there's even a special status code for this, STATUS_GRAPHICS_OPM_RESOLUTION_TOO_HIGH), but conveniently omit to mention that this resolution, roughly 800×600, covers pretty much every output device that will ever be used with Vista.

A Cost Analysis of Windows Vista Content Protection

(A lot of this OPM stuff seems to come straight from the twilight zone. It's normal to have error codes indicating that there was a disk error or that a network packet got garbled, but I'm sure Windows Vista must be the first OS in history to have error codes for things like “display quality too high”).

A Cost Analysis of Windows Vista Content Protection

If you're not versed in DRM doublethink this concept gets quite tricky to explain, but in terms of quantum mechanics the content enters a superposition of simultaneously copied and uncopied states until a user collapses its wave function by observing the content (in physics this is called quantum indeterminacy or the observer's paradox). Depending on whether you follow the Copenhagen or many-worlds interpretation of quantum mechanics, things then either get weird or very weird. So in order for Windows Vista's content protection to work, it has to be able to violate the laws of physics and create numerous copies that are simultaneously not copies.

A Cost Analysis of Windows Vista Content Protection

So, go read the whole thing before I quote it in its entirety here. I will also point out that those who do not study history are doomed to repeat it (in the 10th grade). The computer games industry spent the better part of the 80s trying various copy protection schemes and not one suceeded! It's just sad that Hollywood is spending so much money to learn the same lesson.

Saturday, April 07, 2007

Growing rocks and all that

Spring and I went to the Morikami Museum nd Japanese Gardens in Delray Beach, Florida. Quite the calm and peaceful place, much like Bok Tower, only without Saruman and his throngs of Uruk-hai running around the place.

[The Land of Make Believe]
[The Land of Make Believe at Ground Level]
[“See!  I told you!  Squid eyeballs!”]
[And absolutely NO swimming!]
[Sadly this wasn't real, but a cunning fake.]
[This isn't the Bridge over the River Kwai.]
[Lots of pretty flowers]
[A rock garden, and what can't I ignore?  That pine cone.]
[Waves of rocks in the garden]
[Yet another garden for growing rocks.]
[There's a museum over there, along with very small trees.]
[For some reason, I found this very funny.]
[Little trees.]
[Rock Balboa has nothing on these guys.]
[Wow, a Bonsai forest of one tree!]
[These guys were at least 2′ in length!]
[One of several waterfalls.]
[Boca Raton is overrun with these guys.  This wasn't the only fauna we saw though.]
[Yet another rock garden.]
[This place is lousy with rock gardens!]
[And from Japan we hit a pub in Irland.]

Significantly afterwards, in keeping up with our international hopping in South Florida, Spring and I hit a Irish pub for dinner, where I had a traditinal Irish Fish-n-chips, and Spring had a spinage dip with potatoes, which prompted us to ask if the Irish settled Idaho.

Sunday, April 08, 2007

Leeches

A couple of days ago, I was most surpriesed to find a cellphone bill of $450 for the past month. Spring was livid and went about ripping the head and entrails out of our cell phone provider until everything was kosher and our bill had been cut significantly.

So while our cell phone is straightened out, the DSL situation isn't. Hopefully, later this week …


Street music

Leonard Slatkin, music director of the National Symphony Orchestra, was asked the same question. What did he think would occur, hypothetically, if one of the world's great violinists had performed incognito before a traveling rush-hour audience of 1,000-odd people?

“Let's assume,” Slatkin said, “that he is not recognized and just taken for granted as a street musician … Still, I don't think that if he's really good, he's going to go unnoticed. He'd get a larger audience in Europe … but, okay, out of 1,000 people, my guess is there might be 35 or 40 who will recognize the quality for what it is. Maybe 75 to 100 will stop and spend some time listening.”

So, a crowd would gather?

“Oh, yes.”

And how much will he make?

“About $150.”

Thanks, Maestro. As it happens, this is not hypothetical. It really happened.

“How'd I do?”

We'll tell you in a minute.

“Well, who was the musician?”

Joshua Bell.

Via Steven Talcott Smith, Pearls before Breakfast

Joshua Bell. Playing a $3.6M Stradivarius no less.

But you'll have to read the article to find out the results.

Monday, April 09, 2007

See Gregory! I was right!

What I forgot to mention in yesterday's entry was that Spring and I were over at Gregory's house leeching his Internet connection. We both brought our Mac mini's, and Gregory was particularly amused when I brought along my monitor. “But Sean,” he said, “I have plenty of monitors you can use.”

“But,” I said, “I know this one works and is set to my liking. And I get very irate when stuff that should work, doesn't.”

Besides, my monitor is a flat screen, which makes it easier to transport.

So today, I'm at Smirk's house, seeing how Casa New Jersey is still without Internet access. While I did bring my Mac mini here, this time, I didn't bring my monitor, figuring hey, this is Smirk. Like Gregory, he'll have plenty of monitors I can use.

I should have brought my monitor. The one I'm using is way too small for my liking.

Sigh.

Tuesday, April 10, 2007

Killing spammers “for the kids!”

(Again, at Smirk's house, as Casa New Jersey is still without Internet)

I just had this idea, both wonderful and terrifying while wading through the throngs of spam infesting my inbox promising to increase my mortgage by three inches.

The perception I get (and I'm feeling too lazy to do any real research on this) is that a lot of recent legislation has been passed “for the children” or to “protect our kids” from various nefarious minions out there wanting to harm them. And above all, we must protect our kids from S-E-X. To keep them innocent, you know.

So here I am, looking at the umpteenth “Guarantee 15 mins Longer with V1@gRa” spam, and the idea suddenly hits me—go after spammers “for the kids!” Who in their right minds would want precious Isabella and Christopher to sully their innocent eyes with email that has a subject line of “Raise ejaculation volume” or “Boost up your erection!” or even “H0t Teen L3sbi@n S3X!!!!!!!”? Go after these villainous scofflaws for violating the sanctity of our children's eyes (not to mention their tabula rasaesque minds) and maybe we can reclaim our email as well.

And that's why it's so scary—because this might very well work and embolden even more draconian laws “for the children.” Or worse, spammers will adapt and starting shilling DVDs of Barney and the Teletubbies.

Shudder.

Wednesday, April 11, 2007

Exploding light

Since I've been schlepping my Mac mini around to Internet enabled sites, I thought it might make things easier if I cleaned and arranged my work area at Casa New Jersey. While doing this, I found that one of my flashlights has exploded:

[Sproing!]

For whatever reason, the bottom just simply flew off, thus rendering it useless.

[Broke clean off]
[Pieces of light]

Ah well. I think I paid like 99¢ for it years ago, so it's not like it's a big loss.

Thursday, April 12, 2007

“The traffic is going where?”

Ah, nothing like dynamically generated sub-optimal routing.

Smirk had me install a new router for our T1 customers, and the resulting changes in network topology were rather amusing. The expected path for traffic to customer R was “Internet → Core → Edge-02 (the new router) → R” but instead it went “Internet → Core → Core-02 → Customer S → Edge-02 (over Customer S' T1 no less!) → R.”

Ah, it's the multiple paths between the two cores that lower the “cost” for traffic. The fix was easy enough—bump up the “cost” of Customer S' T1 such that traffic will prefer a “cheaper” path and not go over Customer S' T1.


“Khaaaaaaaaaaaaaannnnnnnoooooooooo!”

Bunny was so intrigued with Incubus, the William Shatner vehicle filmed in Esperanto that I mentioned that she rented it.

Boy, talk about bad. At 76 minutes, it felt like a three hour film. Don't let the trailer fool you, it's not all that suspenseful, and about three times slower than you might expect. Except for the nice camera work (but then again, even Plan 9 from Outer Space had decent camera work, technically speaking) and an overwrought performance by William Shatner in Esperanto, there isn't much else to the film to make it worth the time.

Friday, April 13, 2007

Paraskevidekatriaphobia

But it's just a silly superstition, right?

Ri—

Saturday, April 14, 2007

Burt Rutan. Burt Munro. Burt Reynolds. Guys named “Burt” like to go fast.

I just saw The World's Fastest Indian (the motocycle, not a Native American or one who lives on the India sub-continent). A nice sweet story about New Zealand's Burt Munro (Anthony Hopkins) and his quest to run his 1920 Indian across Utah's Bonneville Salt Flats.

Also on the DVD was director Roger Donaldson's documentary Burt Munro: Offerings to the God of Speed, which was nice to see how close Anthony Hopkins got to the character of Burt Munro—very darn close.

Sunday, April 15, 2007

William Shakespeare through interpretive dance

Spring, Wlofie, Bunny and I went to the Bankatlantic Center Frank Sinatra Theatre to see the Russian National Ballet perform “Romeo and Juliet” (thanks to complementary tickets Spring obtained from a fellow cow-orker).

We arrived at the theatre well in time for the performance, and we used the time to avoid paying $20 to park at the Bankatlantic Center Frank Sinatra Theatre and instead parked across the street at the Sawgrass Mills Mall. It was amazing that parking cost so much, considering that every flat surface of the Bankatlantic Center Frank Sinatra Theatre was covered with advertising and sponsor logos (even the urinals were covered!).

They had curtained off one third of the arena and set up a stage area. Our seats were halfway up the nosebleed section, almost opposite the stage, so we had a nice view of the orchestra pit and the stage.

The dancing was good. It's not hard to be impressed with how effortlessly the dancers leapt and pirouetted across the stage. The lighting—for the most part, the lighting was okay but the people working the spot lights could have been much better. Late cues, not spotting random parts above the stage, overshooting the dancers and generally very poor workmanship with the spot lights. And the music? Let's just say that it wasn't much better than a high school orchestra (say, a C-). Very disappointing.

But more annoying (maybe) were the kids just behind us—the oldest might have been five years old. Constantly asking questions and kicking the back of my seat (and Bunny's, and Spring's). They definitely distracted me from my enjoyment of the dancers, and only slightly from the inept spotlights. And it turns out, they were in the wrong seats anyway and after intermission had moved on to annoy some other section of the audience.

Overall, I'm glad we didn't pay for these tickets (retail value: $56 per ticket). I think I had more fun watching Incubus (at least at home, we could heckle the movie).

Monday, April 16, 2007

Wits End at Casa New Jersey

The lack of Internet here at Casa New Jersey is really taking its toll on us. Part of the problem is the Monopolistic Phone Company, who, if they could, would wipe the Internet off the face of the earth. Another problem is the company we're getting DSL through, which seems to constantly drop the ball. Odd, given that when I've had them in the past, they've been nothing but wonderful.

So why don't we drop this company and go with someone else, or even cable?

Because we're not paying for DSL—The Company is. It's a perk and frankly, I'd rather not pay if I don't have to.

Sigh.

The latest news: maybe Wednesday, possibly by Friday.


Wok with Wlofie

Wlofie came across this carbon steel wok while at Wal★Mart that was perfect for the stovetop. He has another wok, but it has a completely round bottom and thus can only cook with it over an actual fire.

[Wok with me, talk with me]

Although, as is, isn't quite ready for cooking.

[See!  Nice, shiny and new!]

It needed seasoning.

And seasoning a wok requires two things—heat, and peanut oil. Wlofie set the burner to “high” and dumped in a few table spoons of peanut oil (which has a highest smoke point of all the cooking oils). As the carbon steel changed to a dark brown to black, Wlofie would rotate the wok over the burner, and add oil as needed. The high heat would burn the oil into the carbon steel, “seasoning” it—basically, coating it with a molecule thick layer that resists sticking better than Teflon.

[One seasoned wok]

Sure, it doesn't look all that great, but as a cooking surface, it's great. And heck, if something does stick, just apply more heat; whatever sticks will soon turn to ash which can then be dumped out (it's the principle behind a self-cleaning oven, which carbonizes any residue).

Tuesday, April 17, 2007

WOOT!

WE HAVE THE INTARWEBS!!!!!

Now, if you'll excuse me, I shall spend the next few hours in an orgy of Internet browsing …

Wednesday, April 18, 2007

Intarwebs!

… okay, make that a few days.


“It was a good run while it lasted … ”

Okay, one neat thing I've come across:

Kongo Gumi also boasted some internal positives that enabled it to survive for centuries. Its last president, Masakazu Kongo, was the 40th member of the family to lead the company. He has cited the company's flexibility in selecting leaders as a key factor in its longevity. Specifically, rather than always handing reins to the oldest son, Kongo Gumi chose the son who best exhibited the health, responsibility, and talent for the job. Furthermore, it wasn't always a son. The 38th Kongo to lead the company was Masakazu's grandmother.

Via kisrael.com, The End of a 1,400-Year-Old Business

And to think, this company has been around as long as some religions …

Thursday, April 19, 2007

“One ring to rule them all.”

I found this in my blogging notes—I'm not quite sure when I made the note, but it might have been when we were Internetless here at Casa New Jersey. Anyway:

From now on, whenever somebody dials your new uninumber, all of your phones ring simultaneously, like something out of “The Lawnmower Man.”

No longer will anyone have to track you down by dialing each of your numbers in turn. No longer does it matter if you're home, at work or on the road. Your new GrandCentral phone number will find you.

Via Instapundit, One Number That Will Ring All Your Phones

I can see that being handy. Not for me, mind you, but for Smirk, so I no longer have to dial first his cell phone, then his office phone, then his home number when I'm trying to reach the man. Me? I'd hate to have this. Then again, I only have a cell phone number (the phone at Casa New Jersey? Only exists for DSL because the Monopolistic Phone Company demands we have it for DSL).

Now, riffing off this, cell phones used to be a status symbol. “Look at me, I'm so important and I make so much money, I can carry a phone with me at all times.” Now that everyone, even kids, have cell phones? And everyone (especially with this service) can be reached 24/7? Look for the powerful and rich to hire people to answer their phones. “Look at me. I'm so important and I make so much money, I can carry a person with me all the time to answer my phone.”

I'm surprised it hasn't happened already.

Friday, April 20, 2007

“Make Millions on the Intarweb!” or “There is no such thing as a free lunch.”

Sean, here's a complimentary
Conference invitation for you and a guest!

Sean, discover how ordinary people and small business owners are creating incomes using the Internet. Also, learn how you can make money using

[Logo for eBay] [Logo for Yahoo!] [Logo for Google] [Logo for msn]

and other online resources!

I first saw this piece of snailmail on my desk on Tuesday. My curiosity was piqued, and hey, it was free. And as long as I called by Monday, April 16th, I could reserve—

Oops. Missed the deadline by one day.

Oh well.

But hey, nothing ventured, nothing gained. Who knows? I could call and still reserve my spot for the Friday noon session in Boca Raton.

Raise your hand if you think they refused my reservation because I missed the deadline? If your hand is up, I have this bridge I want to sell …

Since I could invite a guest with me, and knowing that Bunny had nothing else planned for Friday, she became my guest for this valuable Internet Income Training Seminar provided by a Leading Internet Solutions Provider for Small Businesses and Entrepreneurs—Since 1995! Including a Free Gift! And a dining package for two. A $120 value!

Free lunch? A Free Gift?

How could I not take them up on this offer. One of the most important things I learned in college was never turn down free food (yes, there is no such thing as a Free Lunch™—in this case, we had to suffer listen to a sales pitch for ninety minutes).

So half an hour prior to the seminar, Bunny and I headed over to the Embassy Suites Hotel in Boca Raton.

[The Conference Site]

Going in, I promised myself that I would not spend a dime on anything. And I managed (along with Bunny) to refrain from spending anything while there. The seminar itself was pretty much what I expected it to be—ninety minutes of shilling for their other, all day seminar where you will discover how ordinary people and small business owners are creating incomes using the Internet, all for the low, low price of $20 (which can include a guest). This seminar? A rah-rah meeting with lots of testimonials, but as it says in the small print:

All testimonials are not earnings claims and are not typical. Your results will vary.

And in case you can't read the small print:

All testimonials are not earnings claims and are not typical. Your results will vary (emphasis added).

But the woman sitting next to me was certainly buying into this (at one point, Bunny passed me a note asking if I thought she was a ringer; I wrote back saying no way as she was making way too many notes to be a ringer for this seminar), as the lecturer kept telling us, over and over, how much we would learn if we sign up for the workshop, a nine hour marathon pitch about Internet Marketing.

Now, I signed up for this “seminar” for blog material but there's a limit to what I'll endure. And I doubt there will be much that I'll learn from such a workshop. In fact, there's a curious bit on the back of the “Customer Activation Form” required to attend the workshop:

… I verify that I am not an Internet Service Provider, do not provide website hosting, and that I will not solicit other workshop attendees for any product or service. …

How odd. I wonder what's up with that? So even if I wanted to attend the workshop, I can't (well, I could but I would be misrepresenting myself to StoresOnline and I can't do that).

At least the lunch was decent.

Monday, April 23, 2007

Much to do about nothing

My plan over the weekend was to write several in-depth programming entries, but alas, my “get up and go” got up and went and before I knew it, it was Monday afternoon and I had written nothing.

And instead of trying to backdate a few hastily written entries, I decided not to bother—I'm never satisfied when I try to backdate hastily written entries and besides, what I wanted to write would take several hours per entry anyway, so … one skipped weekend.

Ah well. These mini-Lego models of Star Wars vehicles (link via kisrael.com) should keep some of my readers occupied for a few hours.


Resistance

And while I had read many articles on this shooting for an article I wrote about school bullying not a single one mentioned the role that a firearm played in stopping it. Until today I didn't know the full story.

Luke Woodham was a troubled teen. He felt no one really liked him. In 1997 he murdered his mother and put on a trench coat. He filled the pockets with ammunition and took a handgun to the Pearl High School in Pearl, Mississippi. In rapid succession killed two students and wounded seven others.

He had the incident planned out. He would start shooting students and continue until he heard police sirens in the distance. That would allow him time to get in his car and leave campus. From there he intended to go to the nearby Pearl Junior High School and start shooting again. How it would end was not clear. Perhaps he would kill himself or perhaps the police would finally catch up with him and kill him. Either way a lot more people were going to get shot and die.

What Woodham hadn't planned for was the actions of Assistant Principal Joel Myrick. Myrick heard the gun shots. He couldn't have a handgun in the school. But he did keep one locked in his vehicle in the parking lot. He ran outside and retrieved the gun.

As Myrick headed back toward the school Woodham was in his vehicle headed for his next intended target. Myrick aimed his gun at the shooter. The teen crashed his car when he saw the gun. Myrick approached the car and held a gun to the killer who surrendered immediately. There would be no further victims that day, thanks to armed resistance.

Via Instapundit, When mass killers meet armed resistance.

The above article has more examples of armed civilians stopping mass murderers at schools that are rarely, if ever, mentioned in the mass media.

I have to wonder why? Is there perhaps some bias against guns in the mass media? You'd think that an armed citizenry is anathema to the mass media.

But given our (and I'm talking about the United States here) history and gun culture, trying to remove all guns is pointless. And we have plenty of laws stating who can carry, who can't, and waiting periods. I see no problem with gun carrying citizens. Might make for a more polite society. And what better way to curb crime than to have a criminal ask, “Who might be packing?”

Also, Zach has the right idea—let us remember Emily Jane Hilscher, Ryan Christopher “Stack” Clark, Ross Abdallah Alameddine, Brian Bluhm, Austin Cloyd, Matthew Gregory Gwaltney, Caitlin Hammaren, Jeremy Herbstritt, Rachael Elizabeth Hill, Matthew Joseph La Porte, Jarrett Lane, Henry J. Lee, Partahi Mamora Halomoan Lumbantoruan (died protecting a fellow student), Lauren Ashley McCain, Daniel Patrick O'Neil, Juan Ramón Ortiz, Minal Hiralal Panchal, Daniel Pérez Cueva, Erin Peterson, Michael Steven Pohle, Jr., Julia Pryde, Mary Karen Read, Reema Joseph Samaha, Waleed Mohamed Shaalan (died protecting a fellow student), Leslie Geraldine Sherman, Maxine Shelly Turner, Nicole Regina White, Christopher James Bishop, Jocelyne Couture-Nowak (died while saving the students in her class), Kevin Granata, G. V. Loganathan and Liviu Librescu (died while saving students in his class).

Tuesday, April 24, 2007

Polyglut

In particular, it seems that I often want a program to do 6 different things, and the best way to do 1 and 2 seems to be Lisp, 3 and 4 is in C, 5 is in Prolog, and 6 seems to be assembly language. I've given up on the QuestForThePerfect Language—why can't I just PickTheRightToolFor TheJob for each part, then glom together all the pieces?

DavidCary

Rewrite Code From Scratch

I touched briefly on this topic a few months ago but went off into a different direction. It wasn't until a few days ago when reading The New UCI Lisp Manual (I enjoy reading old software manuals) which had a section on calling PDP-10 assembly langauge from Lisp (and vice-versa) that I recalled the above snippet and found myself once again with the thought of Where did we go wrong? Why can't we do this?

As I wrote then:

The module header contains a value specifying the language type, with values defined for data only, 6809 machine code, BASIC09-I-code, Pascal I- code and COBOL I-code. In theory then, you can construct, say, a pay roll system using a Fortran compiler to generate the math routines into 6809 code, COBOL to generate the business rules, and allow extentions to be written in BASIC. The language type is probably there for two reasons; 1) to know how to run the module, and 2) to figure out what parameter passing conventions to use (if there are any differences between the languages).

An even longer entry to scare away the new readers

It really just comes down to calling conventions and making small enough pieces to link together.

Okay, so maybe it's not that simple. I'm having a hard time seeing how one would mix, say, Perl (with wealth of modules), Ruby (for easy integration with the World Wide Web) and Lisp (hey, if it's good enough for Yahoo Stores, then why not—it certainly beats using COBOL for business logic) into a single coherent program.

But even just thinking about that I can see why it might not be such a good idea after all—the three languages I mentioned are interpreted (even if it's “compiled” into an internal representation, it's just “compiled” into a form that's easier to interpret) with their own internal structure, and each are garbage collected (which means, memory is reclaimed automatically) but it's a safe bet that memory allocated by a Ruby routine can't be freed by a Perl routine (or Bad Things™ may happen), which is why it's not that simple.

Wednesday, April 25, 2007

Polyglut redux

From
"Jeff Cuscutis" <XXXXXXXXXXXXXXXXXXXXXXX>
To
"Sean Conner" <sean@conman.org>
Subject
Re: Polyglut
Date
Wed, 25 Apr 2007 11:42:21 -0400

.net does what you're looking for. You use the language you want or implement your own, (Ruby, Python, managed C++, C#, VB (just kidding!), etc …)—it compiles to an intermediate language, then is run as x86 machine instructions. All .net classes/objects are understood by any net language. Yes, there is garbage collection, I myself an not entirely comfortable with that, but their implementation is supposed to pretty good. It is cross platform (Mono) at least for web stuff, winforms support is in progress.

Write in what language you want, and know that any other language will be able to call your object with no problems.

Pretty cool, even if it is from Microsoft. :)

Jeff

Well … when you modify scripting languages to target a common internal representation (IronPython Python for .net and Ruby for .net for example) then it comes back to calling conventions and piecing it all together (heck, you can even get Lisp for .net and COBOL for .net so you could probably do a mixed language application under .net).

And yes, pretty cool, even if it is from Microsoft.

Thursday, April 26, 2007

Rethinking computer security

I came across this Google Tech Talk about computer security given by Rik Farrow wherein his thesis is that we need to rethink what we're trying to accomplish.

One thought struck me during the discussion on buffer overflow attacks—the Motorola 6809 had two stack pointers, one used by the CPU itself to store return addresses, but another one that I always assumed was supposed to be used solely for parameter passing. So instead of passing parameters on the default stack like, say, the 8086:

MSG.1	DB	'%s',0
MSG.2	DB	'Hello world',13,10,0

	...

	MOV	AX,OFFSET MSG.1
	PUSH	AX		; save on SP
	MOV	AX,OFFSET MSG.2
	PUSH	AX		; save on SP
	CALL	_printf		; return address also on SP

where everything gets pushed onto one stack and you run the risk of overwriting the return address, on the 6809, use the other stack for parameters:

MSG.1	FCS	'%s',0
MSG.2	FCS	'Hello world',13,10,0


	...

	LDX	#MSG.2
	PSHU	X	* push onto the User stack
	LDX	#MSG.1
	PSHU	X	* push onto the User stack
	JSR	_printf	* return address on System stack

Using a separate stack means you only overwrite program data, not critical system information (especially important when arrays are defined on the stack). But, in reading about some of the ways that buffer overwrites can be exploited, this may not foil every attack. But it's a start, and modern CPUs certainly have enough registers to have a separate parameter stack (although in reading interviews with the 6809 designers, it seems the user stack register was meant to construct stack frames on a single stack, much like the x86's use of the SP and BP registers).

That also reminded me of the Intel 432, which treated everything as an object with set memory limits, so gaining a buffer overwrite exploit on a 432-based system would be exceedingly difficult indeed (too bad it died—it's an interesting chip).

But the basic thrust of the talk was that our computer security models are severely outdated and come from a time when a single computer was shared among several people, whereas today, we have a single user shared among computers (or at the very least, a single user per system, and in this talk, he considered something like Apache as a user) using software (say, certain email clients) that accepts code from Lord knows where (say, evil spammers) and simply executes it (because it goes out of its way to press execute the oh so shiny button code). We need to rethink what we want from computer security.

Friday, April 27, 2007

A journalistic call

From
"Malernee, Jamie" <XXXXXXXXXXXXXXXXXXXXXXXXXX>
To
<sean@conman.org>
Subject
vintage computer collecting
Date
Fri, 27 Apr 2007 10:35:25 -0500

Hi,

I'm a writer from the South Florida Sun-Sentinel working on an article about people who collect “vintage” computers as a hobby/passion. I contacted Jay West with Classiccmp.org and asked if he knew any collectors in my area. Your name came up. I would be interested in interviewing you. If you are interested, could you please forward me a phone number and a good time to call. I usually work Mon-Fri, from 9/10 a.m. to 6/7 p.m. Please include your name, age and the city you live in.

Thanks,

Jamie Malernee
Staff Writer
South Florida Sun-Sentinel
(954) XXXXXXXX
200 E. Las Olas Blvd.
Fort Lauderdale, FL 33301

I gave her my phone number, and earlier this evening she called and we spoke for about an hour about collecting old computers, but the odd thing is—I don't really collect old computers any more, as I lack the space and the funds for running the darned things (Lake Worthless Utilties charges a premium in reselling FPL). I still like old computers, but nowadays I prefer the history of computers, and looking through old software (computer languages and operating systems especially) but that isn't really collecting computers.

She asked if I knew anyone else who collected old computers and if so, could I pass them along to her so she could interview more than one person who lives in the area and collects computers (the sad thing is—on the Classic Computer Mailing List, I'm one of only three Floridians, and the only one in South Florida), so if there's anyone else who collects older computers and lives in South Florida, let me know, and I can pass on Jamie's contact information.

Saturday, April 28, 2007

This Film Is Not Yet Rated

Who is Arleen Bates, and why should you care?

Because she has more influence over what you see and don't see at the films than just about everyone else in Hollywood (with the exception of Anthony Hey, Scott Young, Joann Yatabe, Matt Ioakimedes, Barry Freeman, Joan Worden, Howard Fridkin and Kori Jones).

Why?

Because she's a member of the Motion Picture Association of America Film Rating System, which, until the documentary This Film Is Not Yet Rated, had anonymous members, and (again, until the documentary) whose appeals board were also anonymous.

It's an interesting documentary. The MPAA Film Ratings Board, started in 1968, has always had guidelines for each rating, but no hard, fast rules in place for what is and isn't allowed. Normally, this isn't bad—it allows the guidelines to breath and change with the times, but when the decisions are arbitrary, and feedback to the filmmakers non-existant and appeals cannot use other films' ratings in the appeal, and the members of both boards are anonymous, then it's little more than a Star Chamber.

Basically, the MPAA Film Ratings Board is not transparent.

And because it's not transparent, a filmmaker is at the mercy of the board (which, according to the documentary, whose members don't even fit the profile of the Film Ratings Board) who give no usable feedback to the film maker. The whole process seems reminiscent of the following bit from Amadeus:

Emperor Joseph II
Too many notes.
Mozart
I don't understand. There are just as many notes, Majesty, as I require. Neither more nor less.
Emperor Joseph II
My dear fellow, there are only so many notes the ear can hear in the course of an evening. I think I'm right in saying that, aren't I, Court Composer?
Salieri
Yes. Yes, on the whole, yes, Your Majesty.
Mozart
This is absurd.
Emperor Joseph II
My dear young man, don't take it too hard. Your work is ingenious. It's quality work. And there are simply too many notes, that's all. Just cut a few and it will be perfect.
Mozart
Which few did you have in mind, Majesty?

So, the documentary's directory, Kirby Dick, hired a private detective to penetrate the secrecy of the Film Ratings Board, and then submitted the documentary to the Films Ratings Board—it earned an NC-17 for “some graphic sexual content” but did not elaborate further. The appeal was overturned in a unanimous 10-0 vote (or maybe it was a 12-0 vote, it's not clear if two members of the appeal board are voting members). The MPAA was also caught making an illegal copy of the documentary (although that bit is in the deleted scenes section of the DVD and not in the film proper).

The ratings though, are purely voluntary, but in the same way that Microsoft Windows is voluntary—the entire industry is built around using it, and if you buck the trend, you severely limit the audience you have.

It's scary to think just how capricious the Film Ratings Board really is.

This documentary? If you like films in general, this film is a real eye opener in how films are rated.

Sunday, April 29, 2007

“Party all the time!”

Nothing much happened today, except that Spring, Wlofie and I went to Spring's cow-orker's girlfriend's birthday party (which is not quite as bad as when my Mom's aunt went to her (the aunt's) son's ex-wife's husband's birthday party … in another state!).

It was a typical party—much alcohol, grilling, and grilling with alcohol with flames 10′ high followed by much cheering and more “do it again, this time use more!” No one was hurt (as far as my knowledge goes, but I'm sure there was much hurt the following morning) and a good time was had by all (sorry, no pictures—they were either too dark, too blurry, or too good as blackmail material).

Monday, April 30, 2007

Damned if you do, damned if you don't

I came across this article about CFLs perhaps being worse for the environment than the traditional incandescent bulbs:

It's quite odd that environmentalists have embraced the CFL, which cannot now and will not in the foreseeable future be made without mercury. Given that there are about five billion light bulb sockets in North American households, we're looking at the possibility of creating billions of hazardous waste sites such as the Bridges' bedroom.

Usually, environmentalists want hazardous materials out of, not in, our homes. These are the same people who go berserk at the thought of mercury being emitted from power plants and the presence of mercury in seafood. Environmentalists have whipped up so much fear of mercury among the public that many local governments have even launched mercury thermometer exchange programs.

Via Flutterby, The CFL mercury nightmare

and was greatly amused at the unintended consequences of attempting to be enviromentally sound.

Then I came across some additional information about mercury filled CFLs at Instapundit and maybe, just maybe, things aren't quite as bad as they seem.

Personally, I almost wish it were true, just to see the environmental greenies get their panties in a wad and try to spin this (and yes, I'm bad that way).


“Stop all this violence or I shall be forced to kill you!”

From
Rob XXXXXXXXXXXXXXXXXXX
To
sean@conman.org
Subject
need something to blog about?
Date
Mon, 30 Apr 2007 14:36:46 -0400

In case you need something to blog about, check out this new bill being proposed for congress:

http://thomas.loc.gov/cgi-bin/query/z?c110:H.R.808:

Have fun with this one. Department of Peace and Nonviolence indeed.

Of course it's author is the same guy who just proposed a new bill to ban all handguns.

I actually came across this a few weeks ago and thought about blogging it then, but then came to my senses and realized that this has no way of ever passing both Houses and the President's desk.

Well, until the Democrats have a super majority over both Houses anyway (or both Houses and the Presidency).

Then again … given President Bush's lack of vetos …

Naahhhhh. This won't pass. This is too silly, even for us.

Tuesday, May 01, 2007

09 F9 11 02 9D 74 E3 5B D8 41 56 C5 63 56 88 C0

It took the computer industry over a decade and millions of dollars to realize that copy protection just doesn't work. There are too many bored, intelligent and (more importantly) broke high school and college age kids who view copy protection as a game, an intellectual diversion, and will work hours, nay, days to crack a sceme.

It's just sad that the entertainment industry has to learn the same expensive lession over a similar time period.


Which version was I using again?

Sorry if you've signed up for email notification and gotten some wierd notifications over the past twelve hours. That's because there was a show-stopping bug in the code that only now was triggered.

You see, I rewrote the email notification code some time ago, but hadn't fully tested it yet. Then, a few days ago I decided to add in custom error pages and kept having issues. I knew I had done it before, then I realized I did, over there, but the custom error pages weren't working over here. I thought maybe it was a different version of the code.

So I checked out a fresh copy over at the other place to see if I broke whatever it was that made the custom pages work (it was using an older code base there), and it still worked. But since I'm not using email notification over there, the new email notification code was still untested.

So I checked out a fresh copy here. The custom error pages were still broken.

Turns out it was the installation of Apache on the server here (I used the distro-installed version for a change)—seems that it has a directory alias for /error/, which just so happens is what I named the directory. Had I named it /errors/ (plural) things would have worked the first time and all of this wouldn't have happened (or rather, would have happened at a later time).

Sigh.

But I did.

But notice that I hadn't tested the email notification code yet.

Until yesterday and today.

And boy, did things blow up.

The program kept crashing. Normally, that isn't much of an issue (well, okay, it is an issue) because normally, one is in front of the program to watch it crash, but in this case, I wasn't aware of the crash, because I used the email interface.

Now, mod_blog takes the entry (from a web page, a file, or through email), adds it to the archive, generates the new page, and then, if enabled, sends the email notifications.

It was crashing (unbeknowst to me) during the email notifications.

Postfix has been instructed to send emails to a particular address to mod_blog, which it does. But Postfix also notices that the program crashed. So it requeues the email.

And when the program crashes, the update lock it has is released (technically, it's a file lock that the kernel maintains, but hey, the program goes away, so does the lock).

Next entry comes along, process repeats, and Postfix realizes it has some email queued up, and tries to send that at the same time. Now we have two processes trying to update the blog. Normally, this isn't an issue because of the update lock. But the lock is released in an uncontrolled state and …

Things blow up and get ugly.

But what I'm seeing is a blog that failed a validation check, I fix it, only to have it fail the validation check again, which I fix, only to fail the validation yet again, only now I notice that the same entry I thought I fixed twice keeps coming back to haunt me and even worse, the entire front page is a mess, and is remaining a mess no matter what I do.

I tracked the problem down, but I may have sent some spurious notifications in doing so. Once I realized it was the new email notification code (and man, how did I ever check that code in? Leaks memory like you wouldn't believe! Sheesh) I reverted to the old version, cleared out the mail queue and hopefully, got this situation under control.

Wednesday, May 02, 2007

Yeah, yeah yeah, I know … if it ain't broke, don't fix it. But we're phasing out that equipment …

I only stopped by The Office to pick up a cross-over network cable. Oh, I thought, I might as well move the wireless connection to the other router while I'm here. It's not as arbitrary as I make it seem—we're in the process of phasing out one of our routers and the wireless shot to the building behind us is one of the last things still on that particular router. I'm also not in The Office as much as I used to be, so this was a perfect opportunity. It should only take a few minutes, I thought, as I started running a new cable …

An hour later and I think I have things back to normal. I had made the switchover, and it didn't work. After troubleshooting it to the depth of my knowledge (mainly, clearing ARP tables), I decided to give a call to R, the guy who actually handles the wireless shots for us. Turns out, he can't get to some of his equipment. So now we're both trying to trouble shoot the issue when I decide to put things back.

On the way to a customer's site, I get a call from Smirk, asking if I can check on a down server. I tell him I can't as I'm on the way to a customer site to do some work (that required the cross-over cable I mentioned earlier). Since P wasn't available at the time, Smirk said he'd drive to The Office to check it out.

An hour later I'm back at The Office for our weekly meeting. I bump into R, who's headed towards the roof to check the wireless connection. I tell him I'll be in a meeting but if anything comes up, give me a call. I then bump into P, who informed me that the server in question was down because the network cable had worked loose.

Weird.

P and I head over to the meeting and not one minute in the Internet is down. Down hard enough for us to call Dan, the Network Engineer to investigate. Then, R calls, saying his equipment was unplugged from the network!

This is getting weirder by the minute. I excuse myself from the meeting and head over to the Data Center. I meet R there, and sure enough, one of the network cables leading to the wireless shot had been unplugged. Plug it back in, and the wireless stuff comes back online. Then Smirk calls; Dan said our network connection to the Internet was down (small note: we share Internet connectivity with another company—our Internet providers come in through a single router, and are then split out to each company; it was this link between the Internet router and our core router that was down).

Turns out, that network cable was loose.

Gremlins!

We have gremlins in our Data Center!

How else to explain three unplugged network cables?

(Oh, and after everything was plugged back in, I was able to move the wireless connection to the other router without problem—sigh).

Thursday, May 03, 2007

Fixing code

I fixed the small problem in the code and I see that it's behaving itself.

Good.

I also spent some time making sure the codebase on the development server and the webserver were in sync (good thing because they weren't), cleaning up the code (getting rid of code that isn't used) and making sure it's still portable (by compiling it under Mac OS-X).

I also started to address some issues I have with internal duplicate content, which are two different pages having the same content.

Boy, do I have that in spades.

For instance, the link to todays page is http://boston.conman.org/2007/05/03.1 (note the leading zeros) but the link http://boston.conman.org/2007/5/3.1 will also work (note the lack of leading zeros). Google says it doesn't matter, but for me, it's an issue of aesthetics, and I would prefer the former style (with the leading zeros) over the latter (sans leading zero, and yes, mod_blog doesn't always generate links like I want it to). I added code to detect the non-leading zero references (which I didn't do) but was amused to find that I had code to detect some other variations (which aren't used that much, if at all) that's been there probably from the beginning (late 1999).

So I was aware of the issue seven years ago (imagine that!) but didn't finish that particular feature (since getting it running was more of a priority than getting all the fiddly bits right). I suspect I didn't finish it because handling the generalized case will take a bit more code than I expected, in order to generate redirects to a “canonical” URL.

Friday, May 04, 2007

Polyglut redux redux

The CLR has good support for dynamic languages today. IronPython-1.0 demonstrates this. The new Dynamic Language Runtime (DLR) adds a small set of key features to the CLR to make it dramatically better. It adds to the platform a set of services designed explicitly for the needs of dynamic languages. These include a shared dynamic type system, standard hosting model and support to make it easy to generate fast dynamic code. With these additional features it becomes dramatically easier to build high quality dynamic language implementations on .NET. More importantly, these features enable all of the dynamic languages which use the DLR to freely share code with other dynamic languages as well as with the existing powerful static languages on the platform such as VB.NET and C#.

Via Lemon Odor, Dynamic Languages on .NET—IronPython and Beyond

(This post is in reference to “Polyglut” and “Polyglut redux”). My only comment to this news is, “How long will Microsoft hype this, and when will they then pull the rug out from everybody?”

I only mention this because of MFC, OLE, COM and DCOM, just a few of the heavily hyped but long since dropped and unsupported technologies Microsoft developed over the years.

Saturday, May 05, 2007

Responsible party

Oh!

So he's responsible for Scrappy-Doo (Part II, Part III).

Hrmh.

This is almost grounds for not reading his blog anymore, but the story of how Scrappy-Doo was developed is fascinating.

Sunday, May 06, 2007

Another silly date meme

Okay, this one hits at 02:03:04 am today, 05/06/07.

Neat, huh?

Yeah, I didn't think so either.


“Oversight? What oversight?”

Fleen
On what complaint or authority did these detectives say they were talking to you?
Boyd
On the complaint that I may have made terroristic threats through computers. At least, that's what was passed down to me from the State's Attorney through the detectives on the phone.
Fleen
So who is it that you're supposed to have threatened? Is it now law in the state of Maryland that if anybody anywhere unknown to you feels uneasy at something you write, it's a crime?
Boyd
Well, a terroristic threat is an old legal concept. Basically, it's calling in a bomb scare or something similar.

Now, in the second comic, there's the verbatim transcript of what I said that got me fired. And there's a co-worker who overhears it, which as far as I know is what happened. And Ian [McConville]'s drawing resembles someone in the office to an uncanny degree. Of course, he's never met her, because he lives in California.

Via Snarkoleptics, Interview With The Vampire Terror Suspect

This is for Smirk, with whom I've gone back and forth over topics like this. Matt Boyd got fired over something he said at work and was later investigated for making terrorist remarks.

Okay Smirk, how much do you want to bet Matt Boyd's name is on the No Fly List? (Also interesting is this list of people on the list, including a few American military and government workers)


Junk science vs. junk science

Finally, CFL critics like to remind you that CFL bulbs contain mercury, a highly toxic pollutant. This is true. The typical CFL bulb contains approx. 5mg of mercury. (Manufacturers are working to reduce this. Phillips is said to have developed a bulb that only has 1.5mg of mercury.)

If a CFL bulb is broken, special care must be taken to properly clean up and dispose of the remnants to prevent health risks. Further, CFLs must be recycled or properly disposed of to prevent the mercury from escaping into the environment. Here are the federal government guidelines for CFL disposal and cleanup.

What the critics forget to mention, however, is that coal-fired power plants are a major source of mercury pollution. Further, most of this mercury is emitted into the air, and is thus not contained or containable. Mercury in a CFL is already contained unless it is broken, and if properly recycled is fully containable.

Via Instapundit, Everything you wanted to know about Compact Fluorescent Bulbs, including the mercury problem

Snopes weighs in as well (link also via Instapundit), so that pretty much puts the whole “We're gonna die by Mercury poisoning!” thing to rest.

Monday, May 07, 2007

Why do I keep doing this to myself?

IF IT AIN'T BROKE, DON'T FIX IT!

Sigh.

Spring has been complaining that the DSL connection is sluggish. I did some tests and yes, there is a definite bottleneck at the DSL modem.

Now, a few months back when we (The Company) controlled both sides of the connection, it wasn't slow. But back then, I had enough public IP addresses to give both the DSL modem and my firewall (an old 486) a public address. The DSL modem just slung packets around leaving the firewall to do all the filtering and NATting.

When The Company stopped providing DSL (because of the Monopolistic Phone Company charging us about twice their rate) we went with another DSL provider (and The Company is paying for it). Now, because we only got a single public IP address, things on my network had to change. Basically, the DSL modem is now doing the filtering and NATting for my network, and it might not be able to keep up with the load.

So today I tried to fix it. Moved the public IP address to my old 486, gave the DSL modem some private IP addresses and had it route the public IP address to the 486.

It should work. The DSL modem gets the packet for the public IP address on the WAN port but the routing table in the DSL modem should then forward the packet towards my firewall.

Only it didn't work.

The Monopolistic Phone Company (which actually owns the DSLAM—the device that provides DSL) requires PPPoE with authentication (a few years ago this wasn't the case). So the DSL modem does a PPP negotiation, which, for whatever reason, sets the WAN port to the public IP address. Which is not what I want.

And the DSL modem I use doesn't do bridging, which is what I want.

Then Wlofie noticed the DSL modem supported a feature called “PPP Half Bridge,” which seems to do what I want—it forwards packets to the public IP address to a given host.

Only, the host has to use DHCP to get the public IP address, which I don't need because the public IP address I have is static.

But whatever.

I tried it.

It didn't work (subsequent research shows I might have set it up incorrectly—more testing is needed, but later, when I'm calmed down and not “at work”). And it took a ridiculously long time to reset the modem to a factory configuration (because once I set “PPP Half Bridge” mode, I couldn't get to the DSL modem anymore—turns out all I had to do was pull out the ADSL cable and powercycle the DSL modem, but I found that out after reconfiguring the device).

Sigh.

Tuesday, May 08, 2007

How desperate do you have to be to spam someone?

This is rich. I'm starting to get a bunch of bounce messages that look like:

From
MAILER-DAEMON@conman.org (Mail Delivery System)
To
apache@brevard.conman.org
Subject
Undelivered Mail Returned to Sender
Date
Tue, 8 May 2007 05:09:17 -0400 (EDT)
[-- Attachment #1: Notification --]
[-- Type: text/plain, Encoding: 7bit, Size: 0.5K --]

This is the Postfix program at host brevard.conman.org.

I'm sorry to have to inform you that your message could not be delivered to one or more recipients. It's attached below.

For further assistance, please send mail to <postmaster>

If you do so, please include this problem report. You can delete your own text from the attached returned message.

The Postfix program

<porn_dvd_uk@hotmail.com>: host mx4.hotmail.com[65.54.244.104] said: 550
    Requested action not taken: mailbox unavailable (in reply to RCPT TO
    command)
[-- Attachment #2: Delivery report --]
[-- Type: message/delivery-status, Encoding: 7bit, Size: 0.4K --]
Reporting-Mta
dns; brevard.conman.org
X-Postfix-Queue-Id
F272E170C522
X-Postfix-Sender
rfc822; apache@brevard.conman.org
Arrival-Date
Tue, 8 May 2007 05:09:16 -0400 (EDT)
Final-Recipient
rfc822; porn_dvd_uk@hotmail.com
Action
failed
Status
5.0.0
Diagnostic-Code
X-Postfix; host mx4.hotmail.com[65.54.244.104] said: 550 Requested action not taken: mailbox unavailable (in reply to RCPT TO command)
[-- Attachment #3: Undelivered Message --]
[-- Type: message/rfc822, Encoding: 7bit, Size: 1.3K --]
From
sean@conman.org
To
porn_dvd_uk@hotmail.com
Subject
The Boston Diaries Update Notification [1178615356-28614]
Date
Tue, 08 May 2007 05:09:16 EDT

Thank you for your interest in The Boston Diaries. To start receiving email notifications of new entries, you will need to reply to this email. You don't need to do anything other than reply to this email. Once you do that, you'll be entered into The Boston Diaries Update Database.

If you have no idea what this email is in reference to, someone submitted your email address for notification of new entries to my weblog/online journal (at http://boston.conman.org). If you want to, you can still reply and get notifications of new entries, but you can also ignore this and there will be no futher emails from my server. That is, unless someone submits your email address *again* without your knowledge.

Sean Conner

Basically, some spammer is trying to spam people using my Obligatory Email Notification form, but the form is very basic—only one field is supported and the script generates a precanned email to send (shown above). That part is very basic and I don't see what there is to exploit.

Then again, I wrote the code so I know how it works. The spammer (or spammers; it could be multiple people) may be trying to reverse engineer the script. Heck, if they're that curious, I'll send them the code.

But to investigate this a bit further, I modified the code to record the request (where it came from, what the spammer is trying to send) so I can figure out what they're actually trying to accomplish.

Wednesday, May 09, 2007

But I have to ask, “What exactly is the appeal?”

For Spring (and maybe possibly Gregory who loves this type of stuff)—how to make your own drive-in movie theater (link via Instapundit).


How to make a film in just eight hours

If Hoade and I had access to this film school (link via news from me—and yes, I'm still reading his blog) then we might have actually made a film!.

It doesn't sound like a bad deal actually, and if (and that's a big “if”) I lived in southern California, I might actually do it just for the novelty of it all.


Because I'm told to do these things.

Well, it wasn't broken.

So of course, I fixed it.

This time, I managed to phase out the “old” router for the new “router” (even though they were nearly identical) without a hitch.

Woot.

Update on Thursday, May 10th, 2007 at 10:03 am

Not so woot.

I forgot to update the routing information for one customer (technical explaination: I forgot to add their interface to the OSPF cloud).

At least it was an easy problem to fix.

Thursday, May 10, 2007

“Common sense? We don't need no steeenkin' common sense!”

At the botton of an email I received from a friend today, I following bit of legal verbiage appeared:

NOTICE OF CONFIDENTIALITY: The information contained in this email and any document attached hereto is intended only for the named recipient(s). It is the property of XXXXXX XXXXXXXXXX XXXX and shall not be used, disclosed or reproduced without the express written consent of XXXXXX XXXXXXXXXX XXXX. If you are not the intended recipient or the employee or agent responsible for delivering this message in confidence to the intended recipient(s), you are hereby notified that you have received this transmittal in error, and any review, dissemination, distribution or copying of this email or its attachments is strictly prohibited. If you have received this email in error, please notify the sender immediately by return email or by calling (561) XXXXXXXX. Thank you.

I found it amusing.

[The following three paragraphs were written based upon an incorrect assumption. See below for an update]

Let's see … the company my friend works for (and it's not a law firm by the way) is claiming ownership of a stream of bits that have been delivered to my inbox. Well, I think they're claiming ownership of a stream of bits—it can't be the electrons because the electrons used to transmit the bits have long since been recycled into other bits streaming hither and yon. I can't see it being the magnetic flux on the harddrive that's storing the message, because once I delete the email, there is no message with which to claim ownership over (okay, technically, deleting the message isn't enough since the bits comprising the message still exist on the harddrive unless I overwrite the message with a different pattern of bits, which I may have to do).

So, they're claiming ownership over the bits that comprise the message. Or rather, the bits in the order they appear in the message, because the bits in a different arrangement:

((())), ,, ,,,…‥156:ACCD EEF FIIIIIIILNN NOOOTTTTT XX XXXX XXXXX XXX XXX XXXXXXXX XXXXXXXX XXXXXX XX XXXXXXXY aaaa aaa aaa aaaaa aaaaaaaaaaaaa aa ab bbb bbbccccc cc cccccc ccccdddddd dddd ddd ddddd ddd dd ddddd eeeeeeeee ee eeeeeeeeee eeeeeee eee eeeeeee eeeeeee eeeeeee ee eeeeee eeeeeeeeee eeeee ee eef fff fff fff fggggghh hhhhhhhhh hh hhh hhhhhhhh ii iiiii iiiiiiiiiii iii iiiiiiiiii iiii iiiiiii ii iiiiiiiiii ii kll llllllll lllllllmmmmmm mmm mmm mmnnnn nnnnnnnn nnnn nnn nnnn nnnnnnnn nnnn nnnnnnnnnnn no oooooo ooo ooo ooooooo oooooooooooooo oooooooppppp pp ppppprr rr rrrr rrrrr rr rrr rrrrrrrrrrr rr rrrrrrrr rssssssssss ss sss ssss ssssssss ssst ttttt tt tttttt tttttt tttttt ttt tttttt ttttttttttt tt tttttt uuuuu uu uu uuvvvvv vwwwx yyyyyyyyy yyyyy yyy

lose all meaning (except for the preponderance of “X”, which I used to cut out any identifying identification, you can determine with a high likelihood of chance that the text was originally written in English due to letter frequency). Unless they really are claiming ownership of the bits reguardless of order they're in, but that's not made clear.

Now, the part that goes “shall not be … reproduced without the express written consent …” Obviously, I don't have written consent to reproduce the message here on the blog (although I could claim “Fair Use” in this instance) but in reading the email initially I didn't have prior written consent because the very act of receiving the email caused a reproduction to be constructed—a copy from the bits streaming in from the network to electrical charges in memory and then a copy from said electrical charges in memory to the magnetic flux on the harddrive.

Two copies in which I had no written consent for reproduction.

And then there's the four reproductions made when I viewed the email initially (from disk to memory, from memory to network, from network to memory, and from memory to video screen).

I'm thinking their lawyers need a clue-by-four in how email works.

Then there's the last bit that goes “[i]f you are not the intended recipient or the employee or agent responsible for delivering this message in confidence to the intended recipient(s), you are hereby notified that you have received this transmittal in error, and any review, dissemination, distribution or copying of this email or its attachments is strictly prohibited.” Assuming I wasn't the intended recipient of this message, I would have had to “disseminate” the message (from the server to me) and “review” it to see that it was in fact, not intended for me. The theoretical legal implications of this are staggering.

Which is why I found this all so silly.

(And to my friend who sent this—yes, I realize you have no say in this, but that still doesn't mean your company isn't silly for including this in the first place)

Update some time later today

I misread what they were claiming ownership of—the information, not the actual bits.

When I was constructing the different arrangement, I briefly debated about using the original, non-censored paragraph, since the letters would be scrambled anyway. Then I thought that no, someone could conceivably reconstruct the censored portion, by removing the letters in the known portion, and unscrambling the remaining letters, which wouldn't be that hard. Scrambling the letters didn't hide the information enough to my liking, so I kept the Xs (which is what I use to censor information in case the associated CSS isn't used).

Which meant, it really was about the information.


How desperate do you have to be to spam someone? Part II

Okay, two days later and I have more information about that spammer: they're not trying to send email, they're trying to spam guestbooks and forums.

Before I get there, let me explain how the Obligatory Email Notification System works. When you fill in the form, your email address is added to an “optin” list, and an email is then sent. Only when you reply to that email is your email address moved from the “optin” list to the “verified” list and it's from the “verified” list that emails are sent when I make a new entry.

So I decided to check the “optin” list, and boy, was I in for a surprise. I haven't checked the actual “optin” list for, oh, three years or so? It would be an understatement to say the email addresses were predominately sex related. I grabbed one (hcl_tab_tramadol@hotmail.com) and lo, look at all that guestbook spam.

My guess: the spammer searched the net for HTML forms that looked like guestbook for forum forms, and since many guestbook forms have an email field (usually named email) they tagged my Obligatory Email Notification as a possible guestbook script (since it, too, has a field named email).

But here's where things get weird: the only fields they fill out, in regards to my Obligatory Email Notification form, are the fields defined in that form. I had hoped to see some additional fields being sent in, like comments or message (which wouldn't do anything anyway) but nope, the only fields they sent in were the fields defined for my form.

I thought maybe because I didn't have a field named comments or message they weren't sending in such a field. So I added a field named comments (it's a <TEXTAREA> but with a style of display: none).

Still, only the fields I had originally defined were being sent in.

Checking the logs, and yes, the spammer has definely cached the original form (because the spammer is simply doing a POST to the form, and not retrieving it before doing the POST). I'm going to rename the form and see if that has any effect.

One more thing though: It's one spammer doing all this, and while you would think I could just block that one IP address, I can't. That's because this particular spammer, running their script from 72.232.102.130, is using a series of open web proxies to submit the form, so the actual IP address to block changes all the time. So anyone who is getting spam to a guestbook or forum, and you're running Apache, you might want to check the environment variable HTTP_X_FORWARDED_FOR.

Friday, May 11, 2007

A Panel from a Richie Rich comic devoid of any context and presented here without comment

[I wonder why it should work better now?]

Okay, maybe a small comment: makes you want to read the rest of the story, huh?

Saturday, May 12, 2007

The only way to travel

Bunny and I headed down to the Gold Coast Railroad Museum, located in Miami. It was well worth the drive down, to see how the masses travelled prior to the jet age.

In some ways, it's a shame that travel by train isn't as popular as it was, but even if it was, I'm sure that it wouldn't be nearly as nice as riding on the Silver Crescent. If it was, I'd probably be more inclined to travel more.

[This would make a beautiful diner.]
[See?  Now this is a dining car!]
[What people think of when they think trains.]
[I love blueprints.]
[Railroad map of Florida, circa 1904]
[I was not expecting to see this, evidence of our checkered past.]
[I found this passenger car very depressing—the seats are smaller than what you would find on an airplane!]
[The rail equivilent of Air Force One—U.S. Car #1]

Presidential Rail Car, U.S. Number 1

[The Meeting Room on U.S. Car #1]
[The Observation Room on U.S. Car #1]
[Now THIS is a train!]

Silver Crescent

[If travel was like this, I might actually travel more.]
[The bar on the Califorina Zephyr]
[Dig this obersavation lounge.]
[The upper deck looking down towards the observation lounge.]
[On the weekends, you can get tickets to ride this train, either in the caboose or the engine itself.]

Sunday, May 13, 2007

Maybe I'll get a film done someday …

Via Spring, I see that National Novel Writing Month has a new sibling: Script Frenzy, writing a screenplay in a month.

Now, traditionally, a screenplay is measured in pages, with each page approximately translating to a minute of screen time, but in this, they're counting words—20,000 to be exact. However, they scanned a bunch of screenplays and found the average length was 20,000 words, so that's the target.

Sounds intriguing.

I guess it's time to check out The Nine Act Film Structure among other screenplay structures, and dust off the ol' Quick and Dirty B-Movie Plot Generator (which gives more plots than the one found on the Script Frenzy home page).

Monday, May 14, 2007

Lies, damned lies, and mandated government charges on your phone bill

The whole DSL fiasco stemmed from a misunderstanding between Spring and The Monopolistic Phone Company. She felt that she was paying too much for our use of phone, when all we really use it for is DSL. When it was finally resolved, I told Spring that I wanted to see the next phone bill.

Total Current Charges (Due May 27) … $50.30

Odd, considering Spring signed us up for the $13.22/month basic service plan only includes local calling—no other options (including long distance) are part of this plan.

I went over the bill line by line and I finally understand how The Monopolistic Phone Company arrived at such a figure.

First off, the billing period actually covers April–May, and May–June, so it's two months. Even so, it's still twice as much as one would expect. Well, $3.35 of that is due to a miscommunication about what plan we signed up for. Another $5.86 fell under the Government Mandated and Authorized Charges, and break down thusly:

Government Mandated and Authorized Charges
Line # Charge Amount  
5 Charge for Increase in Rates for Federal Universal Service Charge, Due to Changes in the Rules of the FCC (04/06/07–05/05/07) ($.13/mo) .13  
6 Federal Excise Tax 1.34  
7 FL—State Communications Tax 1.06  
8 FL—Local Communications Tax 2.68  
9 Telecommunications Access System Act Surcharge .15 **
10 Emergency 911 Charge. This charge is billed on behalf of Palm Bc Unic County .50 **

The Federal Excise Tax (thank you so much President Clinton for vetoing the repeal of this tax) is 3%. It was a bit confusing, but the two Floria Communications Tax rates are 2.37% for the state taxes (residents are exempt from the state portion of the communications tax, but are subject to the state gross receipts) and 6.02% for the local taxes.

Line 5 is because The Monopolistic Phone Company forgot to bill us at the higher Federal Universal Service Charge Rate for April (it appears to have gone up on April 1st—ha ha–from 63¢ to 76¢).

And lines 9 and 10? Here's what The Monopolistic Phone Company says about those lines:

If you do not pay the rest of your bill, which includes unregulated charges—all of which are identified by ** on your bill:

So, I could avoid paying 65¢ but my (well, Spring's, since the phone is in her name) credit rating will go to hell.

Nice.

And then there's $14.65 worth of charges:

Surcharges and Other Fees
Line # Charge Amount  
11 Fed Univ Svc Chg ($.63/mo) [note—this is the old rate —Editor] .61  
12 FCC Authorized Charge for Network Access ($6.50/mo) [aka Subscriber Line Charge —Editor] 6.28  
13 Storm Recovery Fee .50  
14 FCC Authorized Charge for Network Access 6.50  
15 Federal Universal Service Charge .76  

[I should note that the bill doesn't quite cover the entire month of April, so that's why some of the figures are a few cents low —Editor]

Hmmm … I'm curious about that “FCC Authorized Charge for Network Services” (also known as the “Subscriber Line Charge”) there. Let's see what the Government has to say about it:

What is the Subscriber Line Charge and why do I have to pay this charge?

The Subscriber Line Charge is a fee that you pay to your local phone company that connects you to the telephone network. Local telephone companies recover some of the costs of telephone lines connected to your home or business through this monthly charge on your local telephone bill. Sometimes called the federal subscriber line charge, this fee is regulated and capped by the FCC, not by state Public Utility Commissions. It is not a tax or a fee charged by the government. The money received from the subscriber line charge goes directly to local telephone companies. To ensure that all Americans can afford at least a minimal level of basic telephone service, the FCC will not allow phone companies to charge more than $6.50 for a single line. More information on the Subscriber Line Charge and other charges on your phone bill.

FCC Telephone FAQ

Isn't that already part of the $13.22/month price we're paying?

Oh wait … there's a definitions part of the bill:

FCC Authorized Charge for Network Access

A charge to recover costs associated with connecting to a telecommunications service provider's interstate network. [emphasis added —Editor]

The $13.22/month plan does not include long distance. In fact, in another part of the bill:

You have elected not to choose a local toll carrier for XXX-XXXX

You have elected not to choose an InterLATA Long Distance Carrier for XXXX-XXXX

We're not making interstate network calls from our phone. So I don't see how the FCC Authorized Charge for Network Access applies in either case. I'd like to hear their spin on this.

Ring.

Ring.

Ring.

“Welcome to The Monopolistic Phone Company; we don't have to care. For English, press one—”

Beep.

“Please enter the phone number on the account you are calling about.”

Beep beep beep Beep beep beep boop boop beep boop.

“To pay your outstanding balance, please press one. To hear your outstanding balance, please press two. To avoid us from having a real live human to talk to you, please press three. Please press four. … Oh, all right, to wait for the slight chance that you'll even talk to a human, please press five. To hear these options again, please—”

Beep.

“You may have to give the phone number of the account you are calling about again because we're The Monopolistic Phone Company; we don't have to care.” Five minutes of classical music. I wonder if the RIAA knows about this?

“Hello?” It's a human! Fantasitic!

“Yes, I'm here,” I said.

“Whom am I speaking to?”

“Sean.”

“Okay, and what account do you have a question about?”

“The number is XXXXXXXXXXX and the name on the account is Spring Bew.” Yes, the last name is incorrect on the account, but Spring said not to bother changing it since the account is just for DSL anyway.

“Okay, and what is your question?”

I mentioned the miscommunication about which plan we signed up for, and over the course of half an hour of listening to classical music, I was able to recover the #3.35, so that's good. Then I asked them about the “FCC Authorized Charge for Network Access.” “What is that all about?”

“It's a Federal mandated charge for connecting to our network, sir.”

“But I checked the FCC website,” I said. “And it says, ’it is not a tax or a fee charged by the government. The money received from the subscriber line charge goes directly to local telephone companies.’ So, how is that any different than the $13.22 you're charging for the account?”

“It's different, sir, because it's a state mandated charge.”

“A state mandated charge?” What? First it's Federal, now it's state? Methinks the operator knows not what we're talking about.

“Yes.”

“Even though it's from the FCC?”

“It's a state mandated charge.”

“But how is that any different than charging me $13.22 for connecting to the network?”

“It's mandated by the state. If you want, you can call the FCC about it.”

“Okay … ”

“The phone number is 1-888-225-5322.”

“Thank you.”

“Is there anything else?”

“No, that's it.” And the call was ended.

Okay, let's see what the FCC has to say about this.

Fifteen minutes of navigating through the FCC phone system, and listening to a definition of the “FCC Authorized Charge for Network Access,” I was able to talk to an actual human there (and for any RIAA moles out there, the FCC phone system plays no music whatsoever when on hold). The operator was sympathetic to what I was saying, but said that the advertising practices The Monopolistic Phone Company engaged in, selling a $13.22/mo plan and tacking on an addtional $6.50/mo, wasn't illegal (note, didn't say “legal”—there's a subtle difference there). It's also not “mandated.” It's optional, and the local phone company can charge nothing for this, but if they do, they can only charge up to $6.50 (more if there are additional lines or a commercial business).

But note that word there—“optional.”

The operator was also surprised when I mentioned that The Monopolistic Phone Company told me it was a state mandated charge. “Congress and the FCC set that charge,” I was told. “You might get some answers if you call the State Public Service Commission. The number is 1-800-342-3552.”

“That's the number for Florida, right?”

“Yes it is.”

“Thanks,” I said. And that call was ended.

Now, on to the Public Service Commission.

Oh, they were closed by the time I got around to calling them.

Guess this will have to wait until tomorrow then.

Tuesday, May 15, 2007

A light delay in my investigative reporting …

I was unable to call the Public Service Commission today as I needed to help light a T1 that was supposed to light last week but was delayed until today, and to help light a Metro Ethernet circuit that we were expecting to light up sometime during the next Ice Age (The Monopolistic Phone Company sure keeps us on our toes).

Perhaps tomrrow …


How desperate do you have to be to spam someone? Part III

After writing about this potential guestbook spammer, I changed the program name for the Obligatory Email Notification script to see what would happen.

Not terribly surprising, Mr. 72.232.102.130 stopped spamming my form. I guess his spamming software was smart enough to handle 404 errors (although technically, I should return a 410 response code but … eh, whatever).

Three days later, and someone else (and I suspect it's someone else, since the email addresses being submitted are “from” colleges and universities, and are not from Gmail, like Mr. 72.232.102.130 was using) is now spamming my Obligatory Email Notification script.

The first spam seemed to be a test (submitted a comment of “Hi My Name Is ivahag.”) but the rest appeared to be the type of spam you would find on a guestbook (“buy this male performance enhancer drug online!”) and at first, I couldn't figure out why the spammer was linking to the faculty page at East West University in Bangladesh.

But then I checked the source code (and this is why I'm not linking to this):

</BODY>
</HTML>
<html><iframe width=0 height=0 frameborder=0
src=http://www.kgeba.com/portal/index.php?aff=razec marginwidth=0
marginheight=0 vspace=0 hspace=0 allowtransparency=true
scrolling=no></iframe></html>
<html><iframe width=0 height=0 frameborder=0
src=http://www.kgeba.com/portal/index.php?aff=razec marginwidth=0
marginheight=0 vspace=0 hspace=0 allowtransparency=true
scrolling=no></iframe></html>
<html><iframe width=0 height=0 frameborder=0
src=http://www.kgeba.com/portal/index.php?aff=razec marginwidth=0
marginheight=0 vspace=0 hspace=0 allowtransparency=true
scrolling=no></iframe></html>
<html><iframe width=0 height=0 frameborder=0
src=http://www.kgeba.com/portal/index.php?aff=razec marginwidth=0
marginheight=0 vspace=0 hspace=0 allowtransparency=true
scrolling=no></iframe></html>

Lovely!

Here's how this works.

The spammer plasters links to the faculty page at East West University in Bangladesh in guestbooks for hot search terms based around male fertility drugs. Some poor sap who's Porsche 911 didn't help goes looking for said male fertility drugs and comes across the links to the faculty page at East West University in Bangladesh (due to the page rank generated by all the links) and thinks he's about to score cheap male fertility drugs.

Only what he sees is a list of academics at some obscure university on the other side of the world and goes back to some search engine to locate other sources of male fertility drugs (and Lord knows what type of ads I'm going to start getting from Google AdSense based on this entry). But unbeknownst to our inadequate feeling fellow, his browser has just generated four requests to some site that pays out money based upon page views. Since the page was requested by a real browser, the assumption that said site makes is that someone viewed the page from a link by Mr. Razec (or who's affiliate code is “razec”) and so Mr. Razec's account is credited by some small amount.

Which, over time, adds up.

Neat little scam, isn't it?

So yesterday I changed the names of the fields for the Obligatory Email Notification form, changing email to atthingy and comments (which, if you remember, is a non-displaying <TEXTAREA>) to blahblah and sure enough, Mr. Razec picked up on the changes and spammed the form again.

Only this time, the link he sent is to a guestbook that's already been spammed.

Wednesday, May 16, 2007

“Hey, let me own that for a while!”

Via news from me comes this little fluff piece about the Avis Car Rental company. What I'm confused by though, is the business of Avis—is it car rentals, or being bought out?

The story of Avis goes something like:

Warren E. Avis (1946)

Richard Robie (1954)

Amoskeag Co. (1956)

Lazard Frères Co. (1962)

ITT Corporation (1965)

Avis (1972)

Norton Simon (1977)

Esmark (1983)

Beatrice Foods (1984)

Kohlberg Kravis Roberts & Company (1986)

Wesray (1986)

PHH Group, Avis Europe P.L.C (1986) (see article)

Avis, employee owned (1987)

General Motors 26% ownership (1989)

HFS (1996)

Avis goes public (1997)

Cendant 34% ownership (1997)

Cedant (1999)

Avis Budget Group (2006)

and I'm sure a lot of people got rich along the way, but what exactly did they do?

I mean, other than push some paper back and forth?

Thursday, May 17, 2007

Stuck

Sigh.

I'm stuck here at a client site, waiting for either G, our Cisco consultant, to call back, or Smirk to return, around 7:30 pm, whichever happens first.

I know what the problem is—I just don't know how to solve the problem using Cisco equipment.

Update a few minutes later

Ah! G just called! He's going to swing by the client site in about half an hour and help us out. Until then, I have to sit tight here.

Thankfully, there's a Linux box I can use in the meantime ...

Friday, May 18, 2007

At the saltmines

Still stuck at the client site.

It's actually been a rather crazy week here at The Company, as Smirk is trying to wrap up as much as possible before a business trip next week.

Today, bonding two T1s together (to make them appear as one 3Mbps pipe instead of two 1.5Mbps pipes) and a pair of new managed switches at another company site, and then finding out their firewall is totally inadequate since it's a consumer model, not one meant to handle a 50+ computer network.

Then, on to the other client site (same as yesterday) to totally reconfigure the site network (shared among three companies—we're providing Internet access to the building they're in), which was something I wasn't expecting, and while there are no show stopping problems, it is taking longer than expected.

One of these days I'll get around to calling the Public Service Commission (perhaps unsurprisingly, it's the same circuits we were dealing with earlier this week).

Saturday, May 19, 2007

I've seen my share of sunrises, but I never get up for them.

We left the client site at 5:30 am.

Ugh.

And we still have a ton of stuff left to do before Smirk leaves for Charlotte next week. Me? I got a ton of equipment to configure for Charlotte.

Ugh.


Spammers—can't live with them, can't take them out behind the shed with a sawed off double barrel shotgun …

I got my very first comment spam today, on my LiveJournal account (which has since been deleted):

XXXXXXXX gives users access to some of the best games and reviews online. No need to waste your time looking for your arcade fix. XXXXXXXX.com is the hub of online gaming. Flash, Java and Shockwave powered high-quality games, 24 hours a day, 7 days a week! If you're not sure, you can choose trial!!! Vizit http://XXXXXXXXXXXX/

When I saw that it was authenticated through OpenID (see also: Wikipedia) my initial thoughts were: OpenID is dead. It's just too easy for spammers to set up self-authorizing hosts (or obtain “accounts” at AOL or even LiveJournal).

Perhaps I'm overreacting. Perhaps spammers are only targetting accounts with no (or very little) activity on them (I have the account to respond to friends who do use LiveJournal; my posting an entry once-per-year is mostly a joke). But I do expect to see more and more of this in the future.

Sunday, May 20, 2007

The Odd Couple

In the years that followed and up until his death, he'd come to see me every time he was in California. We'd have interesting philosophical conversations. We'd exchange personal Christmas cards. He'd show me pictures of his grandchildren. I was with him in Florida once when he complained about his health and his weight, so I suggested that he go on a diet that had worked for me. I faxed a copy to his wife when I got back home.

The truth is, the reverend and I had a lot in common. He was from Virginia, and I was from Kentucky. His father had been a bootlegger, and I had been one too in my 20s before I went into the Navy. We steered our conversations away from politics, but religion was within bounds. He wanted to save me and was determined to get me out of “the business.”

Via news from me, Larry Flynt: My friend, Jerry Falwell

Larry Flynt.

Jerry Falwell.

Friends.

Now that's an odd couple.

I also think it's neat that Larry Flynt has nothing but good things to say about Jerry Falwell, showing that one doesn't have to be a Christian to forgive and forget, or at least, be friends with your enemy.


Yet another restaurant story I can tell

A group of us (Spring, Wlofie, Jessica, her boyfriend Rob and their friend Brian) went to a Chinese/Japanese restaurant in Coral Springs.

When the waiter brought us the check, he mentioned that we caused a fellow member of the wait staff to quit. It seems that when we were seated, the “wrong” waiter was assigned to our table, which upset the “right” waiter so much that he quit, right then, after working there for some twenty years.

Such drama.

And here I thought I left that back in high school.

Monday, May 21, 2007

Small forays into multiprocessing programming

% a parallel sudoku solver.  each cell on the grid is a separate
% process, aware of - and negotiating with - its "neighbours" (those
% cells it must not conflict with).

% a cell is very simple - it contains just two integer values as
% "mutable" state: the current digit and a "confidence" in that value.

% the negotiation protocol is defined below.  cells "ping" the
% controller when the exchange results in a change of value.  the
% controller stops the system when there has been no change in any
% value for CONTROL_TIMEOUT (currently 1s).

% this is terribly, terribly brain-dead and inefficient (takes several
% - sometimes tens of - minutes to solve the test case on my newish
% linux box).  tuning the doubt parameter may help slightly (a value
% of 0.1 seem to work).

% i think some very interesting graphics could be generated from this
% code - think of the solution as a kind of crystallisation, with
% competing centres of nucleation.  please contact me
% (andrew@acooke.org) if interested...

Parallel Sudoku Solver in Erlang :o)

It's an intriguing little program, written in Erlang, to solve a certain class of puzzles (Smirk might find this interesting).

But it does point out the problems of multiprocess coding:

There's a bug. I don't know what it is, but there is one - at least one non-certain cell is stuck at a fixed value.

Parallel Sudoku Solver in Erlang :o)

It's not easy, even in seemingly simple programs.

I came across this little gem of a program (this version in C):

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define MAX	32768

int main(void)
{
  double a;
  double b;
  double c;
  int    i = 0;

  for (c = 2 ; c <= MAX ; c++)
  {
    for (b = 1 ; b < c ; b++)
    {
      a = sqrt(c * c - b * b);
      if (trunc(a) == a)
        i++;
    }
  }
  printf("%d\n",i);
  return(EXIT_SUCCESS);
}

This counts the number of Pythagorean triples within the first 32,768 integers. An “easy” way to speed up this program is to spread the calculations across mutiple processors. Easy enough, just break the main loop across the number of processors. So a uniprocessor box will do all 32,768 iterations, while a dualprocessor box, each processor will do 16,384 iterations, etc.

The first attempt broke the calcuations like that—1–16,383 on one processor, 16,384–32768 on the second one. And much to my surprise, the runtime went from 28 seconds on a single processor run to just a mere 27 seconds across two processors.

Well then …

It took some thinking about what's actually going on to find out the way to properly portion out the work (which I'll leave as an exercise to the reader to figure out). And even then, the time on a quad-processor box went from 28 seconds running on a single processor to 12 seconds across all four (where upon the expected time would be 7 seconds across all four, and oddly enough, the total user time accumulated went from 28 seconds on a uniprocessor to 44 seconds across all four, which makes accounting sense, but it's still odd to see), so the speed up isn't quite linear.

Even on a problem that seems simple to partition there are still “gotcha's” along the way.

Update on Wednesday, May 23rd, 2007

A reply to this post.

Update on Thursday, May 24th, 2007

How I got the code to work.

Tuesday, May 22, 2007

We've just spent the past two weeks mucking with their network and this is what we get.

One of our connectivity clients keeps insisting that the connection is slow. And for proof, he shows us the results from the Speakeasy speed test.

Keeeeeeeeeeeeeeeeeeeerist!

“See?” he says, pointing to a result that shows 300Kbps speed.

“Okay,” we say, “that just shows the traffic from here to the Speakeasy network in Atlanta. Try the Chigaco test. See? 2.8Mbps. That test means nothing.”

“But they're in the Central Time Zone,” he said. I swear, I am not making this up. “They're an hour ahead of us.” [I think his reasoning was this: it's about 5:30 pm Eastern when he said this, and as people get home, the network starts getting congested. At least, I think that was his reasoning. —Editor]

Sigh. “Okay, try the New York test. See? 2.9Mbps. The test is meaningless.”

So, why is the test meaningless? Because once the traffic leaves our network, we have no control over speed issues. The only meaningful test is one that runs across their connection to our network. Or maybe across our network to the exit point. But that's it.

Okay, we might have some influence with our carriers for the first hop or so into their network, but that's about the extent of it. But nooooooooo! “I paid for a 3Mbps circuit and by God I want 3Mbps to Afghanistan!” (okay, he didn't say that, but I suspect he still didn't believe us)


Murphy was laughing at me all along

We've been battling with client networks for the past week or so, and I think the problems have finally abated. The last spot of trouble was the new Metro-Ethernet circuit. The Monopolistic Phone Company kept insisting it was 10Mbps clean both ways. At best we could get 3Mbps one way, and maybe 300Kbps the otherway (and no, this is a different client).

Smirk was insistant upon a test using a different router, but I was hesitant. I was fed up (so was Smirk) and I felt that doing a test with a different router would be a waste of time. Well, that, and it would be a bitch to configure the equipment to use VLANs (long story short: it takes some coaxing to get Cisco equipment to support VLAN IDs above 1024, yet our Metro-Ethernet connection requires a VLAN ID above 1024).

Since Smirk signs the checks, he won.

We called G, our Cisco consultant for help. “Well Sean me boy,” he said, “let's work through the theory of what we're trying—”

“Sorry G but I don't want the theory. I just want the configuration to test this thing and be done with it.” Had I not said that, it would have taken us another three hours. Don't get me wrong, I like G—it's just that he tends to be loquacious.

“Oh,” said G. “In that case, type … ” and inside of ten minutes we were running a test.

9.7Mbps down.

9.8Mbps up.

Oh.

Color me surprised.

The Cisco router we were using was defective.

Oh my.

Heh.

Once that was settled, things wrapped up rather quickly.

Wednesday, May 23, 2007

More forays into multiprocessor programming

From
"andrew cooke" <XXXXXXXXXXXXXXXXX>
To
sean@conman.org
Subject
Erlang bugs
Date
Wed, 23 May 2007 08:12:35 -0400 (CLT)

Hi,

Found your page (which references my Erlang Sudoku solver) via Technorati.

I can't for the life of me remember exactly what the cause was for the bug that you mention in that post, but I am pretty sure it wasn't to do with messaging or otherwise related to concurrency. A better explanation of why it was hard to track down is that the program is largely “indeterminate” in that the flow of control is unpredictable (because of random choices rather than concurrency itself).

However, when I added extra communication for the “community” version—http://www.acooke.org/cute/CommunityS0.html—that did have serious deadlock issues that were directly related to concurrency. And I was surprised at how easy they were (ie how easy it was to introduce errors)—I had somehow convinced myself that Erlang made everything much safer. In retrospect its advantage is not that Erlang's message passing somehow magically avoids deadlocking, but that (1) it provides a clean framework for thinking about message passing that's nicely isolated and easy to read and manage and (2) assuming you stick to the pure functional parts of the language, state is already explicit and so easier to reason about.

Andrew

(Couldn't see a way to comment on the page, so emailing instead)

Just another datapoint that writing concurrent programs, even in a langauge like Erlang which makes it easy, isn't easy.


More steampunk Star Wars stuff

For Jeff Cuscutis: a steampunk Darth Vader mask.

Way cool.

Thursday, May 24, 2007

Small forays into multiprocessing programming II

So, my attempt at parallelizing the Pythagoran Triples program. I rewrote it as a function to make it easier to parallelize:

struct params
{
  double start;
  double end;
  int    count;
}

int pythagorean_triple(void *data)
{
  struct params *p = data;
  double         a;
  double         b;
  double         c;

  for (p->count = 0 , c = p->start ; c <= p->end ; c++)
  {
    for (b = 1 ; b < c ; b++)
    {
      a = sqrt(c * c - b * b);
      if (trunc(a) == a)
        p->count++;
    }
  }
  return(0);
}

That way, I could then do:

/*--------------------------------------
; the reason for these structures
; is that threads created with clone()
; only get a single pointer parameter.  
; This way, I can pass in more data 
; using that one pointer.
;
; And yes, I'm using C.  Nyah.
;-------------------------------------*/

struct param t1;
struct param t2;

t1.start = 2;
t1.end   = 16383;
t2.start = 16384;
t2.end   = 32768;

clone(pythagorean_triple,threadstack1,CLONE_VM,&t1);
clone(pythagorean_triple,threadstack2,CLONE_VM,&t2);

And I was surprised that it only took one second less when the processing was split using this method than when it ran not split at all.

I ran it several times, and yes, both threads were being created, but one was finishing way sooner than I expected. It was then that I realized the reason—it takes less time to count to a thousand than it does to thirty thousand.

D'uh!

Obvious in hindsight.

Basically, thread one was doing:

for (c = 2 ; c <= 16383 ; c++)
  for (b = 1 ; b < c ; b++)
    ... ;

but thread two:

for (c = 16384 ; c <= 32768 ; c++)
  for (b = 1 ; b < c ; b++)
    ... ;

Now … how to split the load evenly between two (or more) processors? Obviously splitting the range in half wasn't cutting it, but is that the only way to split the workload? What if I were to have one processor do even numbers, and the other one odd numbers? Something like:

for (c = 2 ; c <= 32768 ; c += 2)
  for (b = 1 ; b < c ; b++)
    ... ;

for (c = 3 ; c <= 32768 ; c += 2)
  for (b = 1 ; b < c ; b++)
    ... ;

Yeah, that might work.

And it did—the workload was evenly distributed across the processors. The code slightly changed though:

struct params
{
  double start;
  double end;
  double delta;
  int    count;
}

int pythagorean_triple(void *data)
{
  struct params *p = data;
  double         a;
  double         b;
  double         c;

  for (
        p->count = 0 , c = p->start ; 
        c <= p->end ; 
        c += p->delta
      )
  {
    for (b = 1 ; b < c ; b++)
    {
      a = sqrt(c * c - b * b);
      if (trunc(a) == a)
        p->count++;
    }
  }
  return(0);
}

{
  struct params t1;
  struct params t2;

  t1.end   = t2.end   = 32768;
  t1.delta = t2.delta = 2;
  t1.start = 2;
  t2.start = 3;

  clone(pythagorean_triples,threadstack1,CLONE_VM,&t1);
  clone(pythagorean_triples,threadstack1,CLONE_VM,&t2);
}

This concurrent programming certainly requires a different way of thinking about things. And obvious ways of splitting up workloads don't always work out as expected.

Friday, May 25, 2007

“Stop all this silliness at once!”

Okay, LOLCATS has gone on long enough. Can I please have my computer scientists back please?

Saturday, May 26, 2007

I am so going to hell over this

I have a few friends who will get a kick out of this Flash game (especially Rob, my old roommate). But let me say, that Satan is a very worthy adversary, so beware.

Sunday, May 27, 2007

IP Maps

Via a comment at Strange Maps, I came across this neat IPv4 Map (which is based off this xkcd IPv4 map). What's neat is that this map shows you the ownership of IP blocks. It also allows you to zoom in to see the finer detail of ownership (for instance, Level 3 Communications owns 3.0.0.0/8, but has leased out 4.3.0.0/16 to Verizon).

I think Smirk will like this.

Monday, May 28, 2007

A Lazy Memorial Day Celebration

It was a calm Memorial Day today. The plans originally called for us going to the Palm Beach Zoo (free admission to anyone showing a Military, Military Reserve, Coast Guard, Police, EMT, Paramedic or Fire ID card), followed by grilling burgers, and then a Memorial Day Concert in Boca Raton.

But as the old military saying goes: no plan survives first contact with the enemy, and our plans were no exception (“So … so … who's the enemy?” “Shut up!”). We ended up at Bunny's house grilling burgers and just hanging out all day.

And I think that suited all of us just fine.

Tuesday, May 29, 2007

This is what I get for trying to prove to myself that I'm not lazy.

You know, I thought, I'll get gas later. I get gas at Costco, and while Costco is on the way to Boca Raton, right on the corner of Lantana Road and I-95, it's not on the way. You have to turn left off Lantana onto a side street, then enter Costco on one corner of the lot. The gas station, however, is on the opposite corner of the lot, which requires some deft navigation, since the law in Florida is that “thou shalt make a labyrinth of thy parking lot.” Then the same deft navigation to get out of the Costco lot, back on the side street, then a left onto Lantana Road and an immediate right onto I-95. It's too much of a pain, I thought.

Then another thought from some other part of my brain forced its way to center stage: Boy, are you lazy. And because of that thought, I thought You know, you're right! Just for that, I will get gas!

So I turned onto the side street, into the Costco lot, deftly navigated my way to the opposite corner through a crowded parking lot only to find the lines at the gas station wrapping back around the main Costco building. It was like 1973 all over again.

Screw this, I thought, I'll get gas later as I turned around amidst blaring horns in an attempt to deftly navigate through the Costco lot to the exit.

I then mentally beat up that part of the brain that called me lazy.

Finally on my way to Boca Raton, I noticed that the traffic today was unusually heavy, especially given the time of day. What? I thought. Don't these people have jobs? Now I realize that Florida is one of the major tourist attractions in the United States, but Tourist Season™ is well past and now we're getting to late spring, early summer, when the alligators start to sweat. A tourist with any brains whatsoever should have left a long time ago.

What gives?


A frightening minor epiphany on computer user interfaces

But most systems these days are not designed with linguistic operation in mind. If you have to manipulate the same stuff in the same order every day, you'd welcome being able to reduce that to a single line command (or even batch script) You'd take the effort to learn.

The Return Of The Command Line

I had a minor epiphany when I read that, one that put (shudder) control panels into a new light. I'm still pondering the implications of said minor epiphany, but to quickly get it out: the GUI (and (shudder) control panels by extension) were created to give the end user a consistent, simple and largely non-abstract metaphore for using the computer, but more importantly, one that promotes a shared environment between users (I'm flying blind here, trying to get this out, and “shared environment” isn't quite the right word, but it's close enough for now). By that, I mean that Alice can sit down at Bob's computer and still manage to interact with it without problem.

One could argue that a command line is just as “sharable” an experience as a GUI, but in my experience, it isn't.

Back in FAU, I knew a guy that littered his Unix account (a command-line account, by the way) with scores of shell scripts (“batch scripts”) to do all sorts of things. And these weren't large shell scripts either—they were all one or two line scripts that did stuff like, oh, list the contents of the temporary directory, or search through all files for a particular term and have the output paged. But it wasn't like I couldn't use his environment (say, he asked me for some help) as I could just bypass his score of “commands” for the more tranditional ones one finds under Unix, but our common language wasn't there. He'd type in one of his “commands” and I would have no idea what exactly it did. I would type out a rather long command line, piping the data between Unix commands, and he would look at me like I was crazy for doing all that typing.

It's hard to say it was a culture clash, since we were both “using” Unix, but it was certainly a style clash.

And this “cultural” or “style” difference bit me again years later when Smirk was hired to run a small ISP, and I tagged along as “Unix Sysadmin.” The previous sysadmin wrote extensive scripts to manage the systems in question, and left precious little documentation. These scripts often massaged critical configuration files, and the actual “master” copy was stored somewhere else on the system (most of the time, in the old sysadmin's home directory). Often times I would fix something only to have it break when one of his scripts ran (through cron, or by one of the remaining tech support crew).

In other words, while I developed one way of “talking Unix,” the guy in college developed another way of “talking Unix” and the previous admin of the ISP developed yet a third way of “talking Unix.” And none of us got along (so to speak). This “cultural divide” wasn't on the order of, say, the Queen's English vs. American English, but more like the divide between American English and Bavarian German—the roots are the same, but you'd hardly know it—dialect continuum in the extreme.

GUIs, on the other hand, restrict the language available to the user, thus enforcing an interactive conformity—much like L'Académie française does for the French langauge (or rather, tries to do). It's not so much about enhancing productivity as it is usability in general (or communication, take your pick).

This minor epiphany is actually frightening to me, because looking over my history here, I've decried the language drift and incomprehensibility occuring between hard core Unix users, as well as decried (over and over again, ad nauseam) control panels for restricting how I can interact (and fix usually) the computer.

And like I said, I'm still pondering this.

Wednesday, May 30, 2007

… on the other hand, if it was an IBM Model M …

I metioned a steampunk keyboard a few months ago, and now, it looks like someone is actually making and selling them (link via shadesong). But even though these are made with modern USB keyboards and not an IBM Model M like the original, it's probably still in the “if you have to ask, you can't afford it” range.

Ah well …

Thursday, May 31, 2007

I learned this lesson years ago

It was October of 1998. I was sitting in my cubicle when Chuck, my partner, walked by and dropped some papers in front of me.

“Could you please take care of this,” he said. “Mmmm-kay? Thanks. Bye.” He then wandered off to terrorize the sales department.

I read the papers in front of me, and was rather alarmed to find out I had been served a cease and desist letter from some law firm representing the company that owns the trademark to “Welcome Wagon®” who took exception to this particular page on my site.

Now, at the time, I was working for Armigeron Information Services, Inc and my personal website at the time was appearing under the URL of http://www.armigeron.com/people/spc/. I think that the fine people who owned the trademark Welcome Wagon® took offense that my use of Welcome Wagon® fell under a commercial site and using due diligence to protect the Welcome Wagon® trademark, sent Chuck, as owner of Armigeron Information Services, Inc., a cease and desist letter. Now, because the particular page fell under my personal website there on the company site, the letter got passed to me to take care of.

I had no idea that “Welcome Wagon®” was a trademark!

I didn't even create those pages!

I was hosting those pages as a favor to a group of people hanging out in the USENET group alt.society.generation-x of which I was an active member at the time.

It was at that time that I registered my own domain, conman.org (since the obvious choices, spc.org, spc.com and spc.net, were already taken), and moved my site from http://www.armigeron.com/people/spc/ to http://www.conman.org/people/spc/ and configured the company website to send permanent redirects from the old location to the new location (and thus, that's why my personal pages appear under /people/spc/ under my own domain).

That was apparently appeasement enough for the owners of Welcome Wagon® since I've never heard back from them in the nearly nine years since.

I learned two important lessons that day:

  1. companies, no matter how benevolent, will not help litigate that which they do not fully control (in this case, my personal pages under the Armigeron Information Services, Inc. website) and
  2. it's always to your advantage to have your own domain if you want to have any significant Internet presence.

So it's with bemused detachment that I watch the public fervor over LiveJournal suspending accounts willy-nilly. As I posted on a friend's locked journal entry at LiveJournal:

I'm aware of the situation, and I'm of two minds on it. If the accounts deleted were free, then well, you get what you pay for. It would be nice if LiveJournal notified free users of the account being blocked, or whatever, but not legally necessary. If they were paid accounts, then yeah, LiveJournal has some 'splaining to do, and may have acted heavy handed.

But bookshop's 7 Day Response plan is just way over the top. Dude, download the LiveJournal code base, and set up your own fanfic LiveJournalesque site. You perceive a demand for it, and LiveJournal has shown they're not interested. Pick up the market! Make money! It's the American Dream!

Sigh.

This is one reason why I maintain my own server. I'm not beholden to some large faceless corporation to maintain my data for me (then again, I am beholden to a corporation that houses my server, but that corporation is The Company, so I have a bit more autonomy than if I had a sever at, say, DreamHost—and believe me, I am very grateful for that).

To those who can't maintain their own server (or can't afford their own server), I can only say, “read the fine print closely” (“The Bold Print Giveth, and the Fine Print Taketh Away”) and make sure you understand exactly what you are getting into and you can't do, and the company whose services you are using, can do (years ago, I got an idea that involved the use of Moveable Type, but when I read the fine print I realized that I couldn't do what I planned as Six Apart would sue me out of existence).

And another tip: the Internet treats censorship as damage and routes around it. And there's probably money to be made in that …

Update on Thursday, June 7th, 2007

Since writing this, Six Apart has announced a licensing change for Moveable Type---it's now open source under the GNU GPL.

Figures it would change after I mention it.


Alas, it's also not based upon the IBM Model-M

It looks like it took two years, but Optimus Maximus keyboard is for sale! (link via spin the cat) They even have a demo of the keyboard so you can see how it works.

Unfortunately, it's a bit pricey; at $1,600.00, I don't think I'll be getting one any time soon …


“That's your problem!”

It's been over a week since I mailed in my Netflix rental and I still haven't received my next film. Curious to see if it may have been lost in the mail, I check, and oops—my Netflix queue is empty!

Heh.

Friday, June 01, 2007

Love, Rachel.

The store was first opened by J.R. Robinson around 1987 in a single mobile home. It was then sold to Jim & Sue Lindow, who eventually defaulted on it. The store was closed for several years until D.C. Day reopened it as the Quik Pik. He expanded it to double-wide and now leases it to his son and daughter-in-law, David and Burnadine Day. After D.C.'s death in July 1997, his widow Fay Day managed the store.

In 2006 the Quik Pik was sold to an investor from California, who managed to ruin the small but steady business within a few months. It was closed in the winter of 2006/2007, along with the adjacent trailer park. The nearest gas is now 60 miles south, in Ash Springs, or 110 miles north, in Tonopah.

A Short History of Rachel, Nevada: Businesses

I was actually rather sad to read this bit of news. When Hoade and I visited Rachel back in 2005 (the write- up was done in 2006), we actually shopped at the Quik Pik store (got some ice cream) and talked with Fay Day who was managing the store at the time.

And now—it's closed. Probably for good.

How bad do you have to manage a store with a complete monopolistic lock over an entire region and have it fail?

Reading the entire history of Rachel left me feeling melancholy. Here's a small town in the middle of nowhere that's slowly dying and on its way to being a small somewhat amusing footnote in American pop history.


Clue-by-four on track nine …

I have one final comment about the whole LiveJournal blowup: has no one at Six Apart read Cluetrain Manifesto? I thought this was supposed to be baked into online businesses' DNA or something …

Saturday, June 02, 2007

Little pink flamingos for you and me

BOSTON—The original pink flamingo lawn ornament, the symbol of kitsch whose obituary was almost written after its central Massachusetts manufacturer went out of business, is rising phoenix-like from the ashes and taking wing to upstate New York.

A manufacturer that bought the copyright and plastic molds for the original version plans to resume production in Westmoreland, N.Y. HMC International LLC will pick up where Union Products Inc. left off last year when it shuttered its Leominster, Mass., plastics factory after 50 years of making flamingos.

Flamingos back from the dead (link via Bunny)

Back in October, I reported on the demise of the plastic pink flamingo, but I'm happy to report that the pla stic pink flamingo has been taken off the extinction list.

Sunday, June 03, 2007

The things I do to configure equipment

It was a little easier this time since I wasn't shoving raw wires into the female DE-9 connector, but pre-crimped wires. Still, working out which way the wires go took a few diagrams to get it straight, so to speak.

So, for my own notes, the wiring diagram for the BayTech DS9 with the DS72 module with a roll-over cable (Smirk, you might want to copy this down):

BLUE	→ pin 4 DE-9
ORANGE	→
BLACK	→ pin 7
RED	→ pin 3
GREEN	→ pin 2
YELLOW	→ pin 1
BROWN	→ pin 5
WHITE	→ pin 8

and for a straight through cable:

BLUE	→ pin 8
ORANGE	→ pin 5
BLACK	→ pin 1
RED	→ pin 2
GREEN	→ pin 3
YELLOW	→ pin 7
BROWN	→ 
WHITE	→ pin 4

Monday, June 04, 2007

My predictions come true

I forgot about this.

Fortunately, I kept a copy, because my prediction that these 2005 predictions would be swept under the carpet were true!

And so were the 2006 predictions, oddly enough. I'm thinking that ol' Fred there was getting some heat about failed predictions, because his current predictions for 2007 are not only served up using Flash (making it harder to quote), but contain this lovely bit of verbiage at the bottom:

No part of this publication may be reproduced, stored in a retrieval system or transmitted in any form or by any means, electronic, mechanical, photocopying, recording, scanning or otherwise, except as permitted under Sections 107 or 108 of the 1976 United States Copyright Act, without either the prior written permission of Fred Fassett. Please write to XXXXXXXXXXXXXXXXXXXX.

Predictions 2007

Hate to tell you Fred, but your predictions have been reproduced, stored and transmitted, electronically, just for me to read the darned things. The same goes for anyone reading the page, including your loving fans.

Now, as for his predictions in 2005 … well … I read over the predictions, and there isn't any that I can actually point to and say “it came to pass” or even “it failed” because they're all so … obtuse. It's hard to see what he was even predicting, except for his “[s]oon there will be some very strange life forms coming out of the oceans,” but since he's got the hedge word “soon” it's hard to qualify this one either way.

And his current predictions? Most are the “safe” type—cures for cancer and AIDS, weather will get more extreme, economy will strengthen but spending will be cautious, stock market will be unreliable (heh), etc. And a few are of the woo-woo type: “more genius children will be born with more spiritual cognizance with messages from the spirit world,” and “Western medicine and alternative therapies will be combined—doctors will have to go back to school.”

So Fred, I'm not terribly impressed. And removing your past predictions? Tsk, tsk, poor show.

Tuesday, June 05, 2007

Intellectualizing things into the ground

Thinking that things were going to calm down now that Smirk was headed off to Charlotte for a major server installation, I figured I might go through our DNS records and insure they're consistent. Mainly because the major server installation is going into a second facility up in Charlotte, so we're expanding quite a bit.

Unfortunately, the DNS records are a bit of a mess, what with old records that have accumulated, making it difficult to figure out what's used and what isn't. There's also the problem that we have three types of servers—the physical servers, virtual servers (a complete operating system installation on a simulated machine) and what I'll call pseudo-servers, which are basically glorified websites with their own IP address. It's not always clear what is what (yes, our internal records could be a bit better, but it's an issue we're aware of).

I'm stumbling over the fact that I want to organize the DNS records, but I'm not sure how I want to organize them. Right now, the records are pretty much flat—that is, we have alpha.example.net, bravo.example.net and charlie.example.net, but alpha and bravo are here in Boca, while charlie is in Charlotte (and delta.example.net will be in the second Charlotte location). It's one way of doing things, and it's not bad, since for the most part, we don't care where the servers are physically located. But then we need to filter traffic for bravo and that's a virtual server and you can't really filter the traffic on the virtual server, you need to filter it on the actual server it's running on. I don't remember if that's alpha or romeo. (Or does romeo even have virtual servers? Am I mixing it up with juliet?) And is this level of information even something I want to have in DNS?

And then there're the routers. Since I started at The Company our network has expanded quite a bit (enough to make OSPF worth while) and dealing with traceroute becomes an issue. About a year ago, I set up DNS records for the various routers with the names encoding the interface being used. But in the past year, not only have certain routes changed (say, the other end of se0-0.router.customer was moved from se2.edge1.bct.rt to se0-1.edge2.bct.rt (where rt is “router” and bct is the airport code for Boca Raton)) but the interfaces have changed as well (for example, going from a single T1 serial connection to a multipoint link binding multiple T1s). So is the interface type important to know? Or just the router? (I'm thinking—just the router). Also, note the name I gave our edge router—edge1.bct.rt. Conceivably, this means I can create a DNS zone rt, which contains all our routers. But by the same token, I'm inclined to create a DNS zone bct, which contains the routers located in Boca Raton.

Basically, is name.bct.rt better or worse than name.rt.bct?

I don't know. But I do know that we have stuff other than routers that's somewhat datacenter centric, like managed switches we have in Boca, as well as Charlotte (airport code of ctl).

Ah … I'm thinking too hard on this. Time for some Dicewars

(oh, and it turns out Smirk didn't leave for Charlotte today after all—too much stuff came up at the last minute and pushed his trip back a few days)

Wednesday, June 06, 2007

“Because it's never to early to plan for retirement”

Today, Bunny dragged me along to a retirement money management seminar being held at the upscale Boca Raton restaurant Pete's (which I've always confused with Pete Rose's Ballpark Café which is just down the street. The difference? You don't have to take out a second mortgage to eat at Pete Rose's). She received an invite over a week ago, and since it included a free dinner ... Spend an hour listening to a financial pitch to eat a gourmet dinner?

If there's one thing I learned in college, it's “never turn down free food.”

The pitch wasn't that bad actually, much less intensive than the web seminar we attended a month ago, but I do have to wonder about some of the investment programs presented—100% upside, no downside, and some with a payout of 110%? The money has to come from somewhere, and my gut feeling is that it comes from the expansionist money policy the Fed promotes by keeping interest rates dangerously low and inflating the money supply while severely underreporting inflation (so let's see—keep interest rates low and crater the dollar overseas, or strengthen it by increasing interest rates but risk the already shaky mortgage industry and cratering our economy domestically).

But I'm not an economist, nor an accountant, so what do I know?

Anyway, the food was quite good, although Bunny felt that the cinnamon overpowered the subtle flavor of the sweet potatoes (while personally, I felt the cinnamon masked the flavor of the sweet potatoes enough to make them palatable, but then again, I'm not a fan of sweet potatoes). The meal was definitely worth the hour pitch for the financial company offering the seminar.

Thursday, June 07, 2007

This nagging feeling

You ever get the feeling where you know you have to do something, but you've already done everything you need to do? (And yes Smirk, I fixed the <shudder> control panel)

I have that feeling now.

And I don't know what it is I'm supposed to be doing.

I hate this.

Friday, June 08, 2007

Visions of Futures Past

And the exhibit showed electronic cars that we'd all drive to work in 1997, and ways to raise more food for the world through hydroponic greenhouses we'd all use when we went to Mars, and so on. Epcot was originally going to be a huge experiment in sustainable living, but when Disney realized there was no money in that, they had GE, GM, and AT&T drop these huge advertisements for life in the future. And the same thing is, in 1983, it all seemed so fucking feasible that in 20 years we'd all have video phones and TVs with smellovision and pod cars, and I remember that view of the future so vividly. And now that future is in the past, and none of it happened. I used to read in Compute magazine about how, maybe if we all tried hard, cars might have a single microprocessor in them, and it would be so cool to get so much blazing power out of an 8-bit 6510 wired into our engine. And now, I've got at least twenty processors sitting on my desk, in my watch, in my camera, in my mouse, and none of them are doing anything remotely as interesting as what I thought they would be. I have ten times the computing power of that Xanadu house sitting in the battery charger to my camera, and none of it is being used to automatically cook my food or turn on the jaccuzi when I get home from work. And that's sad, in a way.

Tell Me a Story About The Devil: The assorted ramblings of a Midwestern writer in Denver

Xanadu has been torn down, and we still don't have flying cars.

I want my future back!

Saturday, June 09, 2007

It's the end of the world as we know it! Again!

We now predict a terrorist Dirty Bomb or Nuclear Bomb will hit the UN plaza in Midtown Manhattan sometime on or before 2007Sivan30, i.e. before sundown June 18, 2007. We expect it on 2007Sivan20 (June 7–8).

The Lords' Witnesses, the True Bible Code, End Time Chronology

But … but … but … Psychic Fred didn't mention any bombs in his 2007 predictions. But I do like the admission that if nothing happens, “we will not be able to stretch the most specific one of our 20 flexiproofs any further in our present understanding” (“flexiproofs?”). And it's not like they haven't revised their predictions before:

On April 29th we started predicting dates for a terrorist Nuclear Bomb at the UN in midtown. Here are the mistakes we have made …

We no longer make predictions of the precise day. But we do predict it will happen sometime in the month of Sivan 2007—see 20 flexiproofs.

In correcting these incorrect dates we had to improve our chronology several times.

The Lords' Witnesses, the True Bible Code, End Time Chronology

Really? You had to correct your dates several times? I wonder how long it will take before reality sets in?

I'm guessing around June 19th. That is, if the UN isn't a smoking radioactive crater by that time …

God, I love Crank.net.

Sunday, June 10, 2007

Close Encounters

[re—mi—do—do (octave lower)—sol]

Monday, June 11, 2007

WTFHDYUTTMGTIA111111

“Hey, Sean!” It was Smirk, calling from Charlotte. “Can you text message me the IP addresses we're using up here?”

“Um … ”

“Just the numbers, and just make a small ‘R’ next to the router addresses,” said Smirk. “I know how painful sending a text message is.”

“Um … okay,” I said, and hung up.

Okay … down down down down down options … um … no option to send a text message, okay, so backXXXX wrong button … down down down down down, okay, button underneath options—XXXX didn't want to call him, exit exit exit exit, sigh.

Down down down down down details? Okay, options? I guess send message, so down down down down select. Yes, text, so select. 6 4 … how do I … no no no! Not “Oh”—I wanted ”64”. Grrrrr. Back back. Okay, how do I get out of T9 mode# # # # # # # # # # # # I guess it's out of T9 mode by now. 6 4 … no, not “mg” … grrr … 6 6 6 6 4 4 4 4 … okay, the dot … um … how about * 1 1 1 1 3 3 3 3 no, looks horrible. back back back 1 pause 1 1 1 1 3 3 3 3

Oh, XXXX this!

Exit exit exit exit exit exit exit down down down down down call “Hey Smirk, you got a paper and pencil?”

Tuesday, June 12, 2007

“Tanks for the memories …”

At the awakening of the worlds, when
all were alone, and, isolated, fought
many and varied battles unaided,
a voice was heard to cry, “Bolo!”
and warriors found their brothers in arms.

The game takes the form of a tank battle for up to 16 players, set on an island. Players enter the game with their tank on a boat, somewhere off the coast of the island. They move to the island's shore, and leave the boat to drive up onto dry land. Players can shoot at each other, lay mines which only they can see, and engage in battles with the automatic pillboxes which are found on the island. They can also form teams to work together as allies, and can alter the map in various ways. For example, when a mine explodes, it leaves a crater. If the crater is adjacent to sea or river, it will flood with water. Players can build bridges over rivers, and buildings to make a fortress wall, and farm the forests by cutting down trees, to provide the materials for all this building. The forests also grow, not under the control of the players, but in a semi-random fashion designed to appear realistic. All these changes to the map must be communicated to all the other machines in the game so that all players see an identical map at all times. This is the central problem of the project—the maintenance of a distributed replicated database, where some data, such as the location of a particular tank, has a primary site (that player's machine) and some, such as the map and alliance information, does not.

"An Experiment in Real- Time Networking.

Dan W., my friend from FAU, was a big fan of Bolo, but I didn't realize it was the result of a university dissertation.


Aaaaaaaaaaaaaaaaaaaaaaaaaaaaah!

Just … just … just …

Aaaaaaaaaaaaaaaaaaaaaaaah!

Math Education: An Inconvenient Truth (video via Flutterby)

This is how kids are learning math these days?

Aaaaaaaaaaaaaaaaaaaaaaaaah!

Granted, as a student I kept asking what, exactly, was the point of learning my multiplication tables, but I did it anyway. And I cheated all through fourth grade mathematics (which may have eventually led me to repeat pre-algebra in 8th grade), but the techniques discussed here appear to make the traditional method of long division appear easy and straightforward.

I seriously doubt that I would have “found” the way to do long division on my own.

And describe two ways of solving 36 ÷ 6?

Um …

Aaaaaaaaaaaaaaaaaaaaaaaaaaaah!

I am so glad to be out of school, these days.

Updated on Wednesday, June 13th, 2007

Embedding YouTube videos doesn't quite work for me, and it's not because of the blogging engine I use …

Wednesday, June 13, 2007

So much for embedded journalism

Apparently, LiveJournal filters out embedded material (using the <OBJECT> and <EMBED> tags) and drops everything else past that when reading syndicated feeds.

Also, the use of the <EMBED> violates the HTML 4.01 Transitional standard, but without the <EMBED> tag, the video isn't actually embedded.

Sigh.

So I just removed the embedded video and provided a link to it.

And people who read me exclusively through LiveJournal will now know what I'm talking about.


Programming like Lego? I gave that up long ago

[S]oftware is not like Lego; we still do not assemble software from ready-made components as if we were building a Lego house. Almost every programmer has to write low level stuff like if blocks, for and while loops, opening and closing files, creating and deleting resources, thread synchronization etc.

Comment on Code Reads #1: The Mythical Man-Month

I never thought of while loops or opening a file as “low level details.” Twenty-five years ago, “low level” was writing in Assembly language and twiddling bits. But times change, and what was once a high level language (C++) is now considered “bare metal,” much like Assembly was years ago.

But “while loops” and “if blocks” are low level details? I don't necessarily think so. You might be able to hide such things behind more syntactic sugar (just as “while loops” hides the goto it's built out of) but I don't think you'll ever hide them completely (exceptions are one way of hiding a goto but I think that particular cure is worse than the original disease it tried to cure).

And there are others out there who will say we have software Legothe Unix command line. A series of pre-written programs (easily over a thousand such programs) that can be linked together in millions of ways.

Actually, the more I think about it, the more I'm inclined to think that the Legoesque metaphore of software development is not the way to go. We've already been there and have gone beyond it. In its pure form, Lego has a limited number of bricks, in a limited set of colors, which can be used to build just about anything you can imagine. That is, if you don't mind your resulting thing looking a bit blocky. The closest thing we have to that in computer science? Other than the command line, the only computer language I can think of that fits that (limited number of commands is the closest analogy I can think of) is Assembly. Moving, shifting, adding (among other mathematical operations) and testing of bits comprise over 80% of Assembly language (the other 20% Shifting execution to other parts of the program and some other, really esoteric operations usually reserved to the operating system itself).

How many programmers today use Assembly daily?

Not many.

We've got tools that will take a high level concept like:

double A[2][4];
double B[3][2];
double C[][];

C = A × B;

And assemble all the Lego bricks Assembly language instructions required to express the concept (in this case, matrix multiplication). We'll do better, programming wise, to program at higher conceptual levels, than in trying to make programming like Lego bricks.

(I'm also finding Scott Rosenberg's Code Reads well worth reading)

Thursday, June 14, 2007

Off towards Crystal Waving Territory

It's been a rather hectic day today, mostly over borrowing a video camera from Smirk for a weekend trip I'm taking to Orlando with Bunny. Getting the video camera involved three trips to his house; first time the battery died, so he needed time to recharge it to “finalize” the writable disc inside. A few hours later, I was able to pick up the camera, but had to return an hour later so Smirk could “finalize” one more disc he forgot about.

And between all of these trips I attended Scribal Night and dinner.

Fun fun fun.

Anyway, the trip to Orlando. Bunny and I are headed to the area (taking back roads, much like my last trip) to play our regularly scheduled D&D game‡.

Saturday we're headed to a small town I first read about over 25 years ago—Cassadaga, a New Age haven of crystal wavers. And when I found out about the Nighttime Orb Photography Tour, how could I not go there? Maybe this time I'll see some supernatural phenomenon (do do de do do), unlike the last time I went ghost hunting.

Sunday, we're hoping to catch sight of the largest gator ever built on our way to the Kennedy Space Center, and then afterwards, head back home.

Should be fun, but updates may be sporadic until I get back.

‡Bob is running the game in Orlando this week since he's attending SleuthCon. His game is run over the Internet so we don't have to go, but since some of Bob's other players from the West Coast are showing up, if we do play with Bob in Orlando, we'll be able to meet these players in person.

Friday, June 15, 2007

Driving through Dueling Banjo Country

Our hotel is located just off US-192 in Kissimmee, Florida, and to get there, I decided, like on my last trip, to take the back roads to get to our final destination. The plan consisted of taking US-441 north to Kenansville (north of the more well known Yeehaw Junction) where we would then turn left onto Canoe Creek Road until it runs into US-192, whereby we then take another left until we arrive at the hotel.

Another aspect of this trip is that I wanted to avoid any and all chain restaurants and eat only in local establishments—my own private Feasting on Asphalt if you will. And our first stop was in Okeechobee at a place called the Brahma Bull. A rustic place, it was practically dead when we arrived mid Friday afternoon. I didn't think much of it at the time, but that could be a bad sign.

[Hindus should probably skip this place]

Fortunately, it wasn't. Bunny and I had the special, Fish-n-Chips (using perch instead of the traditional cod) and it was quite good. The coleslaw was particularly good; enough so that Bunny asked for the recipe.

I must note that the men's room theme was rather disturbing—a bull chute—I guess the clientele can get a bit rowdy there.

[Moooooo!]

We then continued northward along US-441, through Yeehaw Junction til we hit the major Kenansville metro area, which consisted of a livestock feed store, a human feed store and what I could only assume was a bar. It was rather difficult to miss Canoe Creek Road, it being the major, and only interesection in Kenansville.

[The Greater Metropolitan Area of Kenansville] [Here's our turn] [The Local Hot Spot]

The ride up Canoe Creek Road was nice, although I was surprised at the high amount of traffic we encountered along the road—about one car every other mile or so. I had expected to be the only vehicle along this road.

And contrary to the title of this entry, Bunny and I encounted not one single banjo player, much less two dueling banjo players, much to our relief.


Geeking out at the end of a long day of travel

Bunny and I arrived at the hotel around 6:00 pm. I was planning on calling Bob, our D&D DM to see where he was, but while Bunny was checking us in, I followed the various signs for SleuthCon and found Bob already set up for our weekly D&D game in one of the conference rooms. He'd even gone so far as to set up a projection screen so that some of the early arrivals for SleuthCon could watch our D&D for the evening.

So I checked in with Bob, and Bunny checked in with the Front Desk. We then found our room, unloaded the car, and then headed back to the conference room to partake of some D&D action.

[D&D Group—yes, we're playing on computers] [I … I have no idea …] [The diabolical plans of the DM]

The only exception to my “non-chain restaurant” rule was tonight, as Bob ordered multiple pies from Pizza Hut. This was the only chain-restaurant food Bunny and I ate during the trip.

Saturday, June 16, 2007

In the Land of the Crystal Wavers

[Make sure you have your crystals ready]

We made it to Cassadaga, although we didn't travel the backroads but instead took I-4 East.

I had planned on arriving before 3:00 pm so we could take a historic tour of Cassadaga, but by the time we got going, it was a bit after 2:00 pm, so speed considerations took over asthetic considerations and thus, the trip up I-4. Cassadaga proved to be a bit futher than I expected, about 60 miles away.

We didn't arrive in time for the 3:00 pm historic tour (but more on that in a bit).

But we were in Cassadaga, a place so thick with mediums you can't wave a crystal without hitting one (as I joked to Bunny).

[Spiritualists here] [and here …] [and here …] [and here …] [and here …] [and here …] [and here …] [and here (and the Purple Rose also does aura photos) …] [but not here, about the only exception] [and don't mind the chem trails]

When we enquired about the tour we just missed, we were informed that the Nighttime Orb Photography Tour (which we planned on taking) included the historic tour normally given at 1:00 and 3:00 pm, only at night, and with the opporunity to take pictures of ectoplasmic orbs (or, whatever they are, and I'll be getting to those in a bit). Fortunately, we didn't really miss anything.


Photographing the unseen

Cassadaga is a small town and everything to really see is on the main street. We poked around the few shops there, and while gawking a large display of polished rocks in small side room of the Purple Rose, a medium came in carrying a Polaroid camera and leading a gentleman to a chair in one corner of the room.

He was having his aura photographed.

The man was a bit skeptical of the whole thing and asked how the camera could take a picture of his aura. The medium answered that the it was a specially modifed Polaroid with a computer (mounted on the bottom of the camera) that could detect the aura and modify the picture to reveal it visually. The gentleman then asked how the computer worked, and the medium professed no knowledge of things related to computers. “I can barely turn them on,” she said.

Okay, so now I have to get a photograph of my aura.

Bunny and I wait around for several minutes until the medium is finished with the previous customer. His first photo was deemed unacceptable by the medium, having entirely too much red, which was “residual auric energy from the previous customer.” She then handed the gentleman a large crystal to hold in taking the second photograph, which turned out “better” as far as the medium was concerned. She then spent several minutes interpreting his aura and handing him a small stone from the rack nearby to help him to boost one of his chakra points.

Once she was free I then asked if I can get my aura photographed while taping the procedure (I had borrowed a video camera from Smirk and had it with me in the store). The medium was a bit reluctant. “My mother, who owns the store,” she said, “generally doesn't allow filming.” Okay. Not terribly surprising really. “But let me ask,” she said, wandering off to another part of the store. A few moments later the medium returns and says that it's okay for me to film the procedure.

I'm guessing that $25 is $25 more than they would have had had they said no.

So I set up the video camera in the small room, angled such that I'm the only one in the shot—I was less concerned about getting her picture than I was her answers to my questions recorded. I asked where she got the “computer” attached to the Polaroid camera, and she said it came as a complete unit from a dealer (like this camera for about $3,000.00).

You don't say?

How curiously expensive.

[Do not taunt Happy Fun Bowl]

Just prior to the medium snapping my picture, a pure tone filled the store. “Hear that sound?” said the medium.

“Yes.”

“That's the Crystal Bowl,” she said. “It's a pure Middle-C tone, filled with red. I hope it doesn't affect your aura.” She sat me down in front of a black cloth, had me hold a quartz crystal I was buying (I happen to like crystals as crystals, and had picked up a nice sized piece of quartz. The medium said the crystal “picked” me, and said I should hold it during the photograph). “Oh dear,” she said as she took the picture. Apparently the pure Middle-C tone of the Crystal Bowl had affected the picture. “I ran out of film,” she said, and scurried off to get some more.

A couple of minutes go by, she returns. We set up again, and my aura is photographed. Apparently the redness of the Middle-C from the Crystal Bowl had waned, because my “aura” had very strong yellow tones (“spontaneous, open, optimistic, friendly, intelligent, healthy”) with white colors over my face (“imagination, insight, higher consciousness”). In fact, of the eight colors of the “chakra,” I was missing blue (“intuitive, peaceful, loyal, calm, tender, good listener”) and I had a very minimal amount of red (“passion, vitality, creativity, energy”). She then rooted around the bins of rocks and handed me a blue stone and a red stone to help make up for the lack of blue and red in my aura.

[I think I look a bit jaundiced myself]

It's amusing though. I'm looking through the meanings of the various chakra colors and I'm seeing only positive traits like “creative,” “compassionate,” “psychic,” and “charming”—stuff that most people would say could apply to them, or would like to think applies to them. What I don't see are any negative aspects, like “jealousy,” “greediness,” “pettiness,” or “gullible.”

I'm just saying.


These entries are taking long enough to create due to the heavy photography, so screw the commentary on this one and let's just see some pretty pictures of the area around Cassadaga, okay? Okay!

[Lake Helen—home of the American Gothic Church]
[Delightful Downtown DeLand]
[This place has really good food]

Bill & Frank's Brickhouse Grill—really good food

[Bunny and I kept hearing bells—I think this is where they were]

Little fluffy orbs

Bunny and I arrived back in Cassadaga well in time for the 8:00 pm Historic and Nighttime Orb Photography tour. We walked up to the bookstore and found a few people sitting around waiting. It turned out that one of them, an older gentleman who looked and sounded like Donald “Screetchboy” Sutherland was actually the Reverend Ben Cox, our tour guide for the evening.

[Our Orb Hunting Group—Rev. Ben is in the center]

He was a wonderful speaker and story teller. He lead us around Cassadaga, telling us the history of the place, along with the various spirits that supposedly live in the various buildings.

[Our guide, Rev. Ben, is one bright fellow]

He then took us to the main Spiritualist Temple in town and explained how not only the church service works, but how séances are conducted in the small red-lit room at the back of the temple.

[Rev. Ben explains the ins and outs of the Séance Room]

Now, about those orbs …

After the tour, he lead us to a small clearing behind the temple and told us that this area was rich with orbs and that we should have no problems with catching one or two, but for the best results, we should use flash photography.

Hmmm …

I took a bunch of photos with and without flash.

Here's a pair (the first is the actual photograph, the second photo has been processed with histogram equalization to pull out more detail) taken without the use of flash:

[lack of flash, lack of orbs]
[enhanced—lack of flash, lack of orbs]

and here's a pair with flash (the “orb” is along the ground just below the tree):

[flash, meet orb]
[enhanced—orb, meet flash]

I took twenty photographs, some without flash, most with, and in every one with flash, there were orbs (in most cases, they were only visible when the image was equalized). In this pair, I present the picture with the most visible orb, along with the equalized version, showing even more orbs floating around:

[What a lonely orb]
[Wait … not so lonely after all!]

What's going on here are light reflections, either from pollen, dust, bugs or even reflections in the lens from the flash. I seriously doubt they're really any form of “ectoplasm” (which Rev. Ben explained is similar to salt water).

[A close-up of the orb]
[Enhanced close-up of the orb]

Overall, Bunny and I felt the tour was worth the price. It was entertaining and informative, and everybody enjoyed themselves. It was interesting to see a real séance room and learn how séances “work.” The Reverend Ben is an excellent speaker and story teller.

And overall, Cassadaga was an interesting place to visit. Quite peaceful, and laid back. It might even make a nice place to take a vacation, if one can keep from tripping over all the crystals.

Sunday, June 17, 2007

The long way home

Not much to report on today. And few pictures.

Our plan for today was to take SR-50 east towards Titusville, pass the world's largest built alligator, hit the Kennedy Space Center, then head south back home.

We left the hotel around 12:45 pm, taking US-192 to I-4 for the few miles north to SR-50. What we did not know was that SR-50 just east of I-4 is Little Saigon. For what seemed like a mile we passed block after block of Asian and Vietnamese stores.

Little Saigon in Orlando? In El Pueblo de Nuestra Señora la Reina de los Ángeles de la Porciúncula, yes, I would expect a Little Saigon. But Orlando?

Go figure.

Eventually, after taking a wrong turn onto SR-520 and having to execute a U-turn back to SR-50, we found it.

[That's 200′ of gator goodness there]

The largest gator ever built, all 200′ of it. And for an attraction that's still active, I would have expected to see more advertising for it somewhere along SR-50 (along the Turnpike, you can't drive 200′ without seeing a billboard for Walt Disney World—or at least, discount tickets for Walt Disney World).

By the time we hit Titusville, Bunny and I were famished from lack of food. We turned south along US-1 (also known as Federal Highway, or Dixie Highway, depending upon where you are) and started our hunt for a suitable eating establishment. After about five miles of nothing, Bunny put down an ultimatum: “The next restaurant we see, we eat.”

The next restaurant we found was a small Chinese take-out place. “Well,” said Bunny, “that rule wasn't cast in stone.” We drove on, and eventually found a place to eat.

[The almost famous Dogs ‘R’ Us]

The Dogs ‘R’ Us Grill. A rarity these days—a local fast food restaurant. Couldn't pass this one up.

And again, it was good.

Either that, or the spice of hunger made it taste all the much better.

But so far on this trip, all the local establishments we ate at were very good and a nice break from all the mediocre conformity you normally get at a national chain restaurants.

By the time we finished eating, it was nearly 4:00 pm, and we decided that it was just simply too late to visit the Kennedy Space Center. So we turned south along US-1.

By the time we hit the corner of US-1 and SR-60, we'd both had enough of the backstreet approach to driving, so we turned west along SR-60, and hit I-95 south back home.

All told, it took us maybe six hours from the time we left the hotel to arrive back at Bunny's house. Whereupon I was exhausted and took a two hour nap.

And thus ended our weekend mini-vacation.

Monday, June 18, 2007

Attack of the Sleeping Storm

I'm not sure if it was residual stress from all the driving I did over the weekend, shaking off some low level cold I may have picked up, or the various cryslals I picked up in Cassadaga zapping my energy, but whatever it was, I slept pretty much the entire day.

When I did wake up around 10:00 pm (yes, you read that right, 2200 hours) Spring said that it might have been the storm that passed through the area today. “Did you fall back asleep around 4 or 5 o'clock?” she asked.

“Yes.” Okay, so I didn't sleep the entire day. I was up for maybe two or three hours though.

“Must have been the storm,” she said. “At that time at Negiyo, everybody was struggling to stay awake.”

How odd …


Is it global warming, or just urban heat islands?

Some quick links before I go back to sleep.

It seems that Anthony Watts is questioning the collection of tempurature data and that the data is showing urban heat islands and not necessarily global warming.

I got the link from Flutterby, which has some further commentary and links about this phenomenon (do do de do do) that's worth reading up on as well.

Tuesday, June 19, 2007

Link dump

I must be feeling better today, as at least I'm conscious.

Anyway, doing yet another link dump, as I'm horribly behind on stuff around here.

The next big thing in computing (via Flutterby), which is about dynamic scaling of computing (or websites).

And then there's the real price of gasoline (via Flutterby again), which states that the price of gasoline here in the States is too low by $3.50/gallon due to government subsidies (and how with the artificially depressed prices, we'll never get around to fully developing alternative energy).

And finally, acquaintance of mine moved to Nicaragua because, as he put it, “I've wanted to … outsource myself to someplace warm and sunny with decent DSL.” Globalization can cut both ways I guess.


The Spiritualists … they're following me …

I was just about to start my car and leave the grocery store parking lot (grocery shopping is normally Monday but I was a bit under the weather so to speak) when this older woman approached my car, holding out a small pamphlet. Letting out a sigh, I rolled down my window.

“Here you go,” she said, handing the small pamphlet. “God bless.” And she wandered off.

I looked at the pamphlet. It was an honest to God Christian Tract.

I think this is the first time I've ever recieved one.

Wednesday, June 20, 2007

Next time, I think I'll skip the pizza as a late-night snack

I was feeling a bit under the weather last night and this morning, and that apparently affected my dreams. They're not exactly nightmares (and oddly enough, that's the second time this week I've referenced that entry) but more the type of dream where everything is normal, yet it isn't.

The one dream I do remember fits that mold. I was in high school, but not the one I actually attended. This one was out in some mountainous region like the Rockies. That's the normal bit. The not-quite normal bit was when the mountains started … liquifying, but that's not quite the right term. But it wasn't exactly like a rock slide either. The mountains just … melted? But no heat was involved. Probably more like the mountains turned into a type of non-Newtonian fluid (much like cornstarch with water), upon which the school was carried upon down into a valley.

Not sure what that was all about, but at least I didn't miss the bus (which is normally the nightmare I have when I dream about school).


Things that make you go “Hmmm … ”

I was working on the Cassadaga entries (yes, I'm quite behind on the entries here) when I was struck by this sudden thought—this:

[This is a chandelier]

and this:

[This is a so called “orb”]

are very similar …

Hmmmm ….

Thursday, June 21, 2007

More of the Victorian influence

Spring likes the current TARDIS interior, but frankly, I can't stand it (although granted, it's just marginally better than the mid-90s interior, which in my universe, never happened). No, I like the standard interior.

But I absolutely love the Victorian TARDIS interior:

[Now that's a console!]

There are, unfortunately, very few pictures of this interior on the Internet, oddly enough. To get some, I actually rented the episode this interior appears in, and grabbed some screen shots:

[Sorry about the color]
[but I wanted the detail]
[so I had to stretch the contrast a bit]

(of course, after I did all that, I found the Wikipedia page for this interior—sigh)

I'm not sure why the producers didn't use this interior more, nor why they even had it to begin with. The information about this particular interior is very hard to come by.

Pity. It's a lovely TARDIS interior.

Friday, June 22, 2007

“I forsee myself getting a license … so therefore, I'm psychic, so give me my license … ”

SALEM - Lawyers have the bar exam. Accountants have the CPA exam.

Should Salem's fortunetellers have to pass a test of their own to prove they're psychic?

City councilors, hoping to crack down on fraudulent fortunetellers, are trying to define exactly how a psychic can become licensed to set up shop in the Witch City. They want candidates to undergo a criminal background check and to either live or run a business in Salem for at least a year.

Via Swift, Salem struggles to sort out psychic “free-for-all’

Funny, Cassadaga also licensed their psychics. Bunny actually asked the Reverend Ben about this, and he said there was a board that certified all the psychics and mediums in Cassadaga.

Go figure.

Saturday, June 23, 2007

“Mars is amazing! Mars is aaaaammmmmaaaaaaaazing!”

Bill Watterson may not approve, but this is funny. Those guys at Robot Chicken are twisted, sick, and hilarious.

Sunday, June 24, 2007

Crazy theremin music

This is for Bunny: a cover of Gnarls Barkley's “Crazy is cool” featuring a couple of theremins (link via spin the cat).

Monday, June 25, 2007

And the title has nothing to do with the film …

I worked on Star Wars Episodes I and II, on the Matrix films, on AI and Terminator 3; yet 25 years later there are ways in which Blade Runner surpasses anything that's been done since. Watching the theatrical release DVD at home with PM reminded me of Scott's genius for creating stunning effects with simple technology.

Via Instapundit, Blade Runner at 25: Why the Sci-Fi F/X Are Still Unsurpassed

An all too short (unfortunately) look at some of the special effects of Blade Runner by Mythbus ter Adam Savage. I just wish he went into a bit more depth on this, but alas …


But, how could it fail? I thought China was Communistic and needn't concern itself with economic viability. Or does this mean Communism, in fact, doesn't work? Oh my! Say it ain't so!

It's rather heartening, actually, to think that we aren't alone in abandoned theme parks. It seems that there's an abandoned theme park in China (via Instapundit).

Tuesday, June 26, 2007

Sometimes, I wish software were alive, so that I could take the occasional program out back behind the shed to put it out of my misery and maybe scare the rest of the little software programs to behave unless they too, wish to spend the last few seconds of life out behind the shed. What? Me? Bitter?

One of our customers has been having this weird email problem for the past few weeks, and the fact that we're still working on it means that we haven't exactly solved it yet, nor have we (rather, I) found the source of the problem (and the problem? Mail from one of our webservers, S, is being sent to our customer's colocated email server, W. Now, email for W goes through our spam firewall B. So, we have S → B → W. But somewhere along the way, the mail is bouncing back to S with the error “Client host rejected: too many connections( 2 ).” Unfortunately, this is on B, the spam firewall, which is an appliance, which means, we have very little control over its operation, but I digress).

Now, because of that, I've been having to check the logs on various servers, which include the spam firewall. The only way to check the logs on the spam firewall is through a web interface. Said web interface is restricted such that connections from certain IP addresses are allowed, all others rejected. That's fine, except when I'm not at Casa New Jersey. Then, checking the spam filewall logs is rather difficult.

So I figured I would install Firefox on my virtual workstation at The Office. I could then run the browser there (which is allowed access to the spam firewall) and have it displayed on whatever computer I happen to be using (assuming I'm using X Windows). So, on my virtual workstation, I issue the following command: yum install firefox.

Problem number one: I haven't fully thought this through (more on this later). Problem number two (and the more immediate problem at this point): I'm using yum, a package management system. Oh, it installs Firefox all right. But somehow in the process of installing Firefox, yum, for some bizarre reason, decides to delete the contents of /dev.

Now, for those of you who might not be familiar with Unix (of which Linux is a derivative), the contents of /dev are special files that enumerate the devices on the computer. Deleting the contents doesn't actually delete the device drivers (code that manage the devices), but it does make it hard for any programs to find any devices to use. Which leads me to problem number three: my virtual workstation is now useless.

How yum deleted /dev (no—scratch that—I know how yum deleted the files, obviously by using the unlink() system call) why yum deleted /dev/ I don't know. There's no reason why installing Firefox should do that. I resist the urge to debug yum and figure out why it did that, and just accept the inevitable fact that ocassionally, yum will just decide to delete /dev (and possibly other useful stuff like /bin or /home/sean/images/pr0n) and get on with my life (and the problem at hand, which is a dead workstation).

I manage to get my virtual workstation in working condition and now I'm able to log in, and run Firefox.

Oh, that's right—Firefox will check for a locally running instance and tell that one to open up a window, because, you know, sending all that GUI traffic across the network makes it run even slower, even though that's what I want, you stupid piece of XXXX!

Sigh.

And it seems that the latest version of firefox doesn't even support the -no-remote option.

Aaaaarrgggl!

So I go do what I should have done in the first place (problem one)—use an ssh tunnel: ssh -L 8080:spamfirewall:443 virtual-workstation. Then I can point my locally running broswer to http://localhost:8080/ and login to the spam firewall.

Now I can get back to solving the actual issue with email.

Wednesday, June 27, 2007

“I think there is a world market for maybe five computers.”

He told me that, in his opinion, all the calculations that would ever be needed in this country could be done on the three digital computers which were then being built—one in Cambridge, one in Teddington, and one in Manchester. No one else, he said, would ever need machines of their own, or would be able to afford to buy them.

Douglas Hartree and not Thomas Watson, Sr. as popularly thought.

And according to Scott Hanselman, we might be headed for that future. Only the five computers of Scott's future are not single computers, but five “hives” of computers providing us with most of our services, with Google, Amazon, Microsoft and Sun (with the fifth “hive” being personal computers running shared computing programs like Folding@home).

And while it seems such an outcome is destined to happen, I personally find it a bit scary, although I can't exactly articulate why I find this scary (other than not having control over my own data or computer) and hopefully, we won't end up with The Big Five.


Cheating

Bunny and I just had a little contest to see who could do the Daily Jumble first—Bunny would do it normally, using her brain and a pen, and I would “cheat” by using the computer. The jumble was:

What the tourists paid to use a cell phone in Italy.

THALC _ [_] _ [_] [_]

SEGUS [_] _ [_] [_] _

RETOAT [_] [_] _ [_] _ _

MEINER _ [_] [_] _ [_] _

[_] [_] [_] [_] [_]
[_] [_] [_] [_] [_] [_] [_]

So, did I have a Jumble solving program? Nope. Just the Unix command line, used like this:

GenericUnixPrompt> grep '^[thalc][thalc][thalc][thalc][thalc]$' /usr/dict/words
catch
hatch
latch
GenericUnitPrompt>

I then had to scan the output list (which isn't a very long list) to find the word that actually matches. In this case, the word can't be “catch” because there aren't two Cs, nor can it be “hatch” since there aren't two Hs, leaving the first Jumble word as “latch.”

A couple of minutes, and I have all four words decoded. I then had to take a call on my cell phone. Bunny was still working on word number three.

A few minutes for the conversation, and I start on the solution. By now, Bunny had guessed half the answer, and was working to figure out the last Jumble word (which is “ermine”). I was working to get the final solution, with twelve letters, split between two words, it wasn't easy. A list of five letter words that can be made from the twelve letters of the solution was too large to scan. So was the list of seven letter words. I bogged down, and Bunny was able to pull in the final answer and win.

Just goes to show you that even when “cheating,” you might not always win (now, had I searched the dictionary list for words starting in a capital letter, I might have won, but that thought didn't occur to me).

Thursday, June 28, 2007

24 employees and 200 servers? What type of company are they running over there?

An apparently sucessful company.

  1. The site is serving up seven billion pageviews a month from 200 servers.
  2. All 24 employees work at a Victorian house in San Francisco
  3. The company has never had a tech quit in 12 years
  4. [It] never holds meetings.

Via Steve Dekorte, The XXXXXXXXXX Secret

The company? Craigslist. I would also note that Craigslist is still privately held, and I fear the day that it isn't just look at Google since they went public.


Computers are cheap, but not power

If you're Google, or any other company building out massive datacenter farms, cheap hardware is a strategic advantage. It means you can build larger and larger datacenters for less money. Computers may be smaller and cheaper than ever, but they still require electricity to operate. You now have a new problem. The electrical power used to drive all that free hardware you've amassed becomes your greatest expense:

All this tells us is that Google's problems aren't necessarily our personal problems. Not exactly news. But if you multiply that result by the tens of thousands of servers in Google's server farm, all operating at near 100% load, it's a whole different ballgame. Efficiency is a strategic business decision for Google. Considering the millions upon millions of computers in the world, more efficient PC power supplies are also part of the greater public good. Do no evil, indeed.

Via reddit, When Hardware is Free, Power is Expensive

Power is a concern at The Company. Not only is it powering the computers, but the support equipment (mainly the honking air conditioning required) that needs to be factored in as well.

In fact, Smirk had me building a ton of firewall boxes (as well as our name servers) out of old Cobalt RaQs, not because they were cheap (well, yes, they are) but because they use very low power. We even tested using a Mac Mini as a very low cost server platform. The RaQs worked well. The Mac Mini … eh.

What's really working well are the virtual servers—running multiple servers on a really large server. That's working for us, as a small webhosting company. Google, on the other hand, is another beast entirely.

Friday, June 29, 2007

GNU news is good news, I guess

Hmmm … it seems that the FSF has finally released the GPLv3 (with an accompanying FAQ).

This means I have to read through it and see if I like it or not, or if I should just stick with the old version 2 of the license for my projects.


Six Things I Learned About Programming

This is an interesting meme: Three Things I Learned About Software While Not In College (via reddit). And a lot of the comments are centering on three things learned in college and out of college.

So I'll play along here.

Three things I learned while at college:

  1. Not many students “got” programming, and far too many were there for the money (ha ha, the joke was on them come the Tech Stock Crash of 2001).
  2. It is possible to get into an upper level class and still have no clue how compilers work (“Where do the comments go?” indeed … ).
  3. Make friends with the system adminstrators—that way, you'll stand a better chance of avoiding … um … “complications” for pranks misunderstandings gone awry.

And the three things I've learned since:

  1. Clear code is better than clever hacks. Especially if you end up maintaining the codebase.
  2. You Aren't Gonna Need It.
  3. Not many people “get” programming, and far too many are proving this in Perl and PHP.

Saturday, June 30, 2007

The thrill of plastic army men

I remember the comic book ads touting a mass of toy soldiers (link via news from me) as a kid, and I was always curious.

But never having the money, nor the desire to actually destroy one of my precious comic books, I was to remain curious about these ads. I always assumed they were like the little green plastic army guys that were omnipresent in my childhood. Even as an adult, I was curious as to what these kits actually were.

And now I know—they're even cheaper and cheesier than the little green plastic army guys. Glad I saved my (non-existent) money.


I don't mean anything by this; it's just an observation, that's all.

Basically, it's that she works great if you don't use her as a substitute for knowing roughly where you're going. You can't follow her instructions mindlessly but she sure helps me get around, even on semi- familiar turf. I'm learning the names of local streets I only vaguely knew and every so often, even when I know how to get where I'm going, I ask her to plot a route and it's sometimes a clever suggestion.

news from me: Heeding Henrietta

This reminds me of an incident that happened over a year ago (obliquely referenced as “Gregory started to drive, but wasn't feeling all that well, so I took over for him”) dealing with a GPS (and Gregory and I have been over this incident many a time before, and I doubt we'll change our respective minds on the situation) but yes, I can agree that GPS works best if you don't slavishly follow its directions.

Then again, I can say the same thing about using computers too.

Sunday, July 01, 2007

Monkeys

I may have been a bit unfair to Gregory in my last post. Sure, I think he takes his GPS lust to a bit of an extreme, and his utter reliance on the thing is totally baffling to me (“Dude, Tom lives in Atlantis!, on the other side of the canal from Casa New Jersey! There are only two ways into and out of Atlantis! What do you mean, how do I get there?”) but I'd be lying if I said I wasn't being totally hypocritical—I was absolutely crazy without Internet. It was frightening just how dependent I was on the thing. The fact that I couldn't look stuff up on a whim, say, rotary wankle engine, or even what is a closure, meant I was at a complete loss when I couldn't do that.

So Gregory, I understand, even as I kid you on your GPS addiction—we all have monkeys on our backs.

Monday, July 02, 2007

Food. At a restaurant.

Spring, Wlofie and I spent the evening having dinner with Mark Hamzy, who I knew in college and probably haven't seen in a dozen years (since IBM moved him to the Republic of Texas and has yet to relieve him of his employment). We ate dinner at Havana in West Palm Beach. The food was quite good there.

Fortunately, we managed to avoid the whole process of selecting a restaurant that we used to employ when in college, which went something like this:

[Cast: Sean “Demigod” Williams (lead vocalist) , Bill “Giant Hogweed” Lefler (keyboards, guitar), Sean “Captain Napalm” Conner (electric clarinet) and Mark “You're a member of our group, damn it, whether you want to be or not” Hamzy (evil eye and set prop). Setting: Bill's room, any given Friday or Saturday.]

Sean (Williams)
So, what do we want to eat?
Mark
Food.
Sean
Sigh. What type of food?
Bill
Edible.
Sean
Okay, where do we want to eat.
I
A restaurant.

And so on, for about an hour. The thing was, we each had an unconditional veto for any restaurant suggestion, except for Mark, who had two (well, rather, he had the one we all have, plus an additional “permanent veto” on all food related to oeans, streams, lakes or rivers). The entire process would take something on the order of two or three hours and there were plenty of times when we got into Bill's car without the slightest clue where we were going to eat and just randomly drove around town until we ran out of vetoes, or we had at least two votes for a single restaurant.

Fun times, but of a different time, and a different place.

Tuesday, July 03, 2007

The dreaded “Early Morning Call”

Ah, nothing like getting a call at the ungodly hour of 10:30 to fix a munged firewall. For reasons I'm still trying to figure out it apparently crashed last night and the fix was a power cycle.

But in looking over the log files, I kept seeing:

Jul  2 08:48:07 localhost kernel: SPOOF-SRC-172 IN=eth0 OUT=eth1
	SRC=172.21.159.36 DST=XXX.XXX.XXX.XXX LEN=40  TOS=0x00 
	PREC=0x00 TTL=238 ID=0 DF PROTO=TCP SPT=11100 DPT=1516 
	WINDOW=0 RES=0x00 RST URGP=0

I had programmed the firewall to reject any private IP address (since you're not supposed to see private IP addresses on the Internet at large) yet here I was, seeing a private, albeit a less known private, IP address. Only the source address kept changing for each packet logged, but always within the 172.21.0.0/24 block.

This meant that the address was originating somewhere on our network, but where?

Pinging one of the private IP addresses from the router directly connected to the firewall didn't show anything. It seems that the ping packets were sent to the main core router, which just dumps private IP addresses to the bit bucket.

But why was that router throwing anything from 172.21.0.0 to the firewall?

Now, the rule I have for filtering these packets in iptables looks like:

iptables --table filter --append FORWARD --source 172.16.0.0/12
	--jump LOG --log-prefix "SPOOF-SRC-172 "

iptables --table filter --append FORWARD  --source 172.16.0.0/12
	--jump REJECT

iptables --table filter --append FORWARD --destination 172.16.0.0/12
	--jump LOG --log-prefix "SPOOF-DST-172 "

iptables --table filter --append FORWARD --destination 172.16.0.0/12
	--jump REJECT

which doesn't record the MAC address (which uniquely identifies an Ethernet interface on a network). However, by adding:

iptables --table mangle --append PREROUTING --source 172.16.0.0/12 
	--jump LOG --log-prefix "WHAT "

the MAC address is logged.

Cool!

Jul  3 17:48:24 localhost kernel: WHAT IN=eth0 
	OUT=MAC=00:10:e0:02:09:dd:00:02:85:12:a7:c0:08:00 
	SRC=172.21.117.49 DST=XXX.XXX.XXX.XXX LEN=40 
	TOS=0x00 PREC=0x00 TTL=239 ID=0 DF PROTO=TCP 
	SPT=11112 DPT=3716 WINDOW=0 RES=0x00 RST URGP=0  

What's recorded is the MAC address of the interface (the first six octets), followed by the MAC address the packet came from (the next six octets) followed by the protocol (the final two octets, and in this case, it's an IP packet).

Now, the first three octets of a MAC address are the vendor code—who makes that particular Ethernet device. Easy enough to look up and—

A Riverstone?

It's the router?

There's nothing on our network that uses the 172.16.0.0/12 private IP space. And yet, here's one of our routers, sprewing forth garbage packets.

Sigh.

Time to get with Dan the Network Engineer on this …

Update on Thursday, July 5th, 2007

Between Dan the Network Engineer and I, the problem was solved.

Wednesday, July 04, 2007

Blowing things up with alien technology

Ah yes, the Fourth of July. The time of year when all Americans go outside and blow stuff up. It looked unlikely that anything would be blown up this year, as it was storming all day, but apparently, it cleared up enough for a few fireworks shows I can now hear going off in the distance.

Besides, there are more things one can do to celebrate the Fourth of July than simply to blow things up, such as indulging in a perennial favorite topic of mine—government conspiracies about aliens and their technology!

PACL was located in Palo Alto, but unlike XPARC, it wasn't at the end of a long road in the middle of a big complex surrounded by rolling hills and trees. PACL was hidden in an office complex owned entirely by the military but made to look like an unassuming tech company. From the street, all you could see was what appeared to be a normal parking lot with a gate and a guard booth, and a 1-story building inside with a fictitious name and logo. What wasn't visible from the street was that behind the very first set of doors was enough armed guards to invade Poland, and 5 additional underground stories. They wanted to be as close as possible to the kinds of people they were looking to hire and be able to bring them in with a minimum of fuss.

One downside to CARET was that it wasn't as well-connected as other operations undoubtedly were. I never got to see any actual extra- terrestrials (not even photos), and in fact never even saw one of their compete vehicles. 99% of what I saw was related to the work at hand, all of which was conducted within a very narrow context on individual artifacts only. The remaining 1% came from people I met through the program, many of which working more closely with “the good stuff” or had in the past.

My Experience with the CARET Program and Extra-terrestrial Technology

Of course, it's well known that AT&T developed the transistor based upon alien technology and that Intel has managed to reverse engineer alien technology to build their latest chips.

But like all great conspiracy theories (and I love these because they're so entertaining) they leave a few things unanswered. In the case of AT&T (or more specifically, Bell Labs), did they even have the technology to reverse something as complex as a microchip? Send back even an old Pentium to Bell Labs in even 1940 (a full seven years before they invented the transistor)—could they even figure out what it was? (I'm assuming they could get the actual chip out of the ceramic casing) Could they even detect a single transistor?

Besides, a transistor is nothing more than two back-to-back diodes in a single package, and diodes have been around since the 1880s.

I received a link to the CARET page from a mailing list I'm on, and as one member of the list commented:

How do you build a “secret” 5 story underground facility in Palo Alto with and

  1. have the right number of cars in the parking lot and
  2. not hit the water table. The industrial parts of PA are either in the flats next to 101 and the SF Bay or are near Foothill Expressway where almost all of the industrial parks are owned by Stanford.

Besides, how do you advertise jobs for such a place?

Oh, and the Intel Pentium being based upon alien technology? That, I can actually buy. I mean, have you ever tried programming that thing? Something that convoluted can only be the result of humans partially reverse engineering alien technology …


“Houston, we have a problem … ”

London, 4th July 2007. Steorn, an Irish technology development company, will publicly demonstrate a real-life application of its Orbo free energy technology for the first time. The demonstration will take place in the Kinetica Museum gallery, London UK on Wednesday 4th July. People around the world will be able to watch the exhibit via a live web stream.

Update 4/7/07 23:30

Due to slight technical difficulties we will now be publishing the live stream as of Thursday 5th July.

Via flutterby, Steorn demonstrates free energy technology in public forum

In keeping with the woo-woo technology, I present you with Steorn, a company premoting free energy, only they seem to be having difficulties …

Hmmmmm ….

Update on Thursday, July 5th, 2007

We are experiencing some technical difficulties with the demo unit in London. Our initial assessment indicates that this is probably due to the intense heat from the camera lighting. We have commenced a technical assessment and will provide an update later today. As a consequence, Kinetica will not be open to the public today (5th July). We apologise for this delay and appreciate your patience.

Steorn Orbo—World First Free-Energy Demonstration

Giggle.

Update on Friday, July 6th, 2007

Further to Steorn's announcement yesterday (5th July) regarding the technical difficulties experienced during the installation of its “Orbo” technology at the Kinentica Museum in London, Steorn has decided to postpone the demonstration until further notice.

Sean McCarthy CEO stated that “technical problems arose during the installation of the demonstration unit in the display case on Wednesday evening. These problems were primarily due to excessive heat from the lighting in the main display area. Attempts to replace those parts affected by the heat led to further failures and as a result we have to postpone the public demonstration until a future date.”

He continued that “we apologise for the inconvenience caused to all the people who had made arrangements to visit the demonstration or were planning on viewing the demonstration online.”

Over the next few weeks the company will explore alternative dates for the public demonstration.

Steorn announcement: Kinetica Demonstration

Why doesn't that surprise me?


“I'm proud to be an American, where at least I know I'm free, living under a system of Law, without systemic corruption and I can blow stuff up for fun, not for survival.”

Such a uniquely backfiring setup was responsible for the world's worst library. A few days after I arrived in Cameroon, I visited one of the country's most prestigious private schools—Cameroon's equivalent of Eton. The school boasted two separate library buildings, but the librarian was very unhappy. I soon understood why.

At first glance the new library was impressive. With the exception of the principal's palatial house, it was the only two-story structure on campus. Its design was adventurous: a poor man's Sydney Opera House. The sloped roof, rather than running down from a ridge, soared up in a V from a central valley like the pages of an open book on a stand.

When you're standing in the blazing sunlight of the Cameroonian dry season, it's hard to see at first what the problem is with a roof that looks like a giant open book. But that's only if you forget, as the architect apparently did, that Cameroon also has a rainy season. When it rains in Cameroon, it rains for five solid months. It rains so hard that even the most massive storm ditches quickly overflow. When that kind of rain meets a roof that is, essentially, a gutter that drains onto a flat- roofed entrance hall, you know it's time to laminate the books. The only reason the school's books still existed was that they'd never been near the new building; the librarian had refused repeated requests from the principal to transfer them from the old library.

Via Flares Into Darkness, Why Poor Countries Are Poor

This is a long article, going into detail about the systemic corruption in your typical African nation, and how difficult it will be for Cameroon to pull itself out of its death spiral. It's well worth reading, and a reminder of just how good we have it here in the west, where we can blow stuff up without worry …

Thursday, July 05, 2007

There is a difference between routing and blocking …

One of these days, I'll get this networking stuff down.

I talked to Dan the Network Engineer about the Riverstone router and it's not the Riverstone that's losing its mind, it's me.

Just because I route outgoing traffic to 172.16.0.0/12 to nowhere on our core router, doesn't mean that incoming traffic “from” 172.16.0.0/12 from “The Outside” (and by “The Outside” I mean, “The Internet At Large”) gets routed to nowhere.

Nope, it gets routed to the destination, which is on the other side of the firewall, which is doing its job and dumping the garbage packets.


Notes on an overheard conversation between a customer of the Monopolistic Phone Company and Technical Support on an email issue

“Hello, this is Bob, The Monopolistic Telephone Company Technical Support Technician. How may I help you?”

“Bob, my emails to Earthlink aren't getting through, but I can still receive emails from Earthlink. Can you help me?”

“Well, my father lives way out in the country, and I don't know where or how the equipment is set up out there, but I think that the cows get in between the equipment and block the signal.”

Friday, July 06, 2007

“And together, they must save Elvis from the Illinois Nazis.”

It was a pretty crummy day today, both at work and at the weekly D&D game. To calm down, I spent a few hours updating The Quick And Dirty B-Movie Plot Generator. Besides the cosmetic change (and boy, did it ever need that) I also fixed the gender pronoun problem it had.

And hey, since it's one of the few pages that gets a few hundred hits a month, I decided to see if some advertising on that page might bring in a few more shekels.

And yes, the entire thing is written in C. Nothing better to calm me down than writing a web-based program in a langauge totally ill-suited for writing web-based programs.

Saturday, July 07, 2007

How Ricky Bary Harbord can be a pregnant former First Lady

Bunny was cycling through various Quick and Dirty B-Movie Plots and was wondering how it worked, because she kept getting stuff like:

Ricky Bary Harbord is a beautiful pregnant former first lady with a song in his heart and a spring in his step. Valeri Barbara Bramlett is a cigar-chomping gun-slinging farmboy searching for her wife's true killer. And together, they must save Elvis from the Illinois Nazis.

“How does it work?” she asked. “How can Ricky be pregnant and the former First Lady? And how can Valeri be a cigar-chomping farmboy?”

“Well,” I said, “I know several women who like smoking cigars.”

“But Ricky as a former First Lady?”

“Sex change operation.”

“And pregnant?

“Okay, you got me there.”

How it works. Basically, it's a template:

<male-name> <male-name> <family-name> is <article> <adjective> <adjective> <occupation> <mission>. <female-name> <female-name> <family-name> is <article> <adjective> <adjective> <occupation> <mission>. And together, they must <joint-mission>.

You know, like all good generative text programs. But I have a single list of adjectives, occupations and missions that I pick from. And while I do adjust the gender specific pronouns, I don't adjust any other gender specific terms, partly because I'm lazy, and partly because it makes for some real amusing plots. Even though it does sound ludicrous that Ricky can be pregnant, if Hollywood can make Arnold Schwarzenegger pregnant, I'm sure they can find a way to make Ricky a pregnant former First Lady.

To save these plots, Bunny had to cut-n-paste them into another document. I then realized that it wouldn't be hard at all to add a bookmark feature to the Quick and Dirty B-Movie Plot Generator—all I had to do was save the random number generator seed and make it part of the URL. And lo' you can now bookmark specific plots that are generated, which is a feature I don't see at They Fight Crime.

Sunday, July 08, 2007

Some thoughts on health care while my dislike of Michael Moore comes through, and a small tangent thought on cheap computers

“Anyone seen Sicko yet?” asked a friend. None of us, and by “us” I mean a group of friends and myself hanging out, had seen the new Michael Moore film. “Aw man,” he said, “it's a really good film.”

“Is there anything about that film that tells us something we don't already know?” I asked.

“There are over 40 million uninsured Americans in this country, getting XXXXXX over by greedy corporations,” he said.

“Um,” said one of the other friends, “Sean said ‘anything we didn't already know.’”

Touchy subject this is.

On the ride home, this friend and I continued in this conversation, agreeing more than disagreeing on what exactly is wrong, but we strongly disagreed on the weaknesses of “universal health care” in other industrialized countries. He was sure that it's not in as bad shape as I think it is overseas (or even across the border), but I found this (on a totally unrelated search) very interesting:

This may seem foolish at first, but despite being in the heart of South East Asia, in what is generally thought to be a developing country, the Thai medical system is unbelievably good. Not only is it the medical hub for [Irish] expatriates throughout the region, but tens of thousands fly here each year to have elective surgery, from laser eye treatments to boob jobs and face lifts. There are lots of reasons why they come to Bangkok but invariably quality of surgery and care comes top of the list. Simply put, medical care in Thailand is amongst the best in the word, available at a fraction of the cost.

Via Justin Mason, Surgery in Bankok

Irish going overseas for surgery. Okay, so this is elective surgery, which appears not to be covered, or it might be very long waiting lists to get it done. But I find it very telling that not only is there a market for elective surgery, but that greedy doctors in Thailand are exploiting the desire for elective surgery to get filthy rich by charging affordable prices—

Wait a second!

Something doesn't sound right there …

I think I know what it is—there's no good market for elective surgery in Ireland (or possibly the rest of Europe by extenstion). You can either wait months or even years for such a procedure, or pay through the nose for private care. Thai doctors, seeing the large amounts of money to be made in elective surgery, have entered the market, but given the lower cost of living in Thailand, prices that would surely be outrageous to fellow Thais are actually quite affordable to Westerners.

In fact, it wouldn't surprise me at all if certain elective procedures even here in the United States are cheaper than comparable, non-elective procedures since the cost is borne solely by the people, and if you want to tap into that market, you have to charge what the market will bear, and what the people will bear is way less than what the insurance companies can bear (when said insurance companies dare to actually bear).

And on a completely different tangent, it's amazing that $300 will get you a fully functional computer. I wonder how that came about?

Monday, July 09, 2007

“Ooh, look! A Monopolistic Phone Company Repair Van in its native habitat!”

Mark just sent me an email pointing out the book Infrastructure: A Field Guide to the Industrial Landscape:

We are surrounded by the hardware of the modern world, but how much of it do we even notice, much less understand? This unique and fascinating book covers the parts of the landscape that are often overlooked despite their ubiquity—objects such as utility poles, power lines, cell phone towers, highway overpasses, railroad tracks, factories, and other man-made mechanical marvels. And they are not just in urban areas, but include out of the way “ecosystems” such as mines, dams, wind farms, power plants, grain operators, steel mills, and oil refineries. In Infrastructure, Brian Hayes offers clear explanations of the systems that keep the modern world running, including agriculture, energy supplies, shipping, air transportation, and the various ingenious methods of recycling and managing the waste we generate.

Review of Infrastructure: A Field Guide to the Industrial Landscape

It certainly sounds like the type of book I would love to read. Thanks, Mark.


Cross-eyed and brain-fried

Spring asked me to go through my photos for the past four years (all are digital photos) looking for pictures that fit some criteria she gave me .

Four thousand, five hundred and fifty digital photos later, I found the twenty-one pictures that fit the criteria.

I'm looking forward to the day when I can instruct the computer “give me all photos with the following characteristics … ”

Tuesday, July 10, 2007

They certainly know how to time power outtages around here

Gotta love Lake Worthless Utilities.

Sometime this morning, I awoke to the squealing of a hungry UPS—it apparently had been squealing for sometime as it was both loud and frequent. I rolled out of bed and began the process of blindly shutting down my various computers. And if I do this in the wrong order, they might not shut down in time due to intercomputer dependencies (gotta love networked drives).

Five minutes after shutting everything down, the power is restored.

Sigh.

I then began the process of turning on my various computers …


There's a reason why a feature that takes five minutes to implement takes ten hours to code …

It seemed like an easy feature to add to the Quick and Dirty B-Movie Plot Generator. All I wanted was the ability to bookmark a particular plot.

What I didn't realize was that the method I used, saving the random number seed, was completely and utterly the wrong thing to do, and that the feature isn't quite as easy to implement as I first thought.

Easy to implement features, aren't.

My first clue? I “bookmarked” a particular plot on my development server:

Sheffie Les Mastenbrook is a mute world-famous card sharp from a doomed world. Susette Marie-Jeanne Sanford-Wright is a virginal green-skinned werewolf with nothing left to lose. And together, they must defuse a bomb in less than a day that's a thousand miles away.

(the bold parts? I'll get to that—and by the way, this is plot #1134)

Later on, I decided to check on the “bookmarked” plot on my deployment server, and got:

Sheffie Les Mastenbrook is a fast talking hunchbacked ad-exec on the run. Susette Marie-Jeanne Sanford-Wright is an orphaned short-sighted boxer with the power to bend men's minds. And together, they must fight crime.

Oops. (Bold text denotes differences between the two versions)

It seems that the random number generator between the two servers isn't quite the same; enough to get the names the same (which are the first things to be generated) but diverge right after that. So, if I wish to keep the URLs valid, I can't change servers, or even update the current server!

From this, I realized another problem—I can't change the data files the program uses! This stems from how I use the random numbers I get, and for this, I need a slight digression.

In C (which is what the program is written in), I call rand() to get a random number. rand() takes no parameters, and returns an integer between 0 and some upper bound RAND_MAX (which is a system and compiler dependant value). The man page (on my development server, which is an older Linux distribution) has this to say on using rand() (sad to say, but the man page on current Linux distributions excludes this excellent bit of advice):

The versions of rand() and srand() in the Linux C Library use the same random number generator as random() and srandom(), so the lower-order bits should be as random as the higher-order bits. However, on older rand() implementations, the lower-order bits are much less random than the higher-order bits.

In Numerical Recipes in C: The Art of Scientific Computing (William H. Press, Brian P. Flannery, Saul A. Teukolsky, William T. Vetterling; New York: Cambridge University Press, 1990 (1st ed, p. 207)), the following comments are made:

If you want to generate a random integer between 1 and 10, you should always do it by

j=1+(int) (10.0*rand()/(RAND_MAX+1.0));

and never by anything resembling

j=1+((int) (1000000.0*rand()) % 10);

(which uses lower-order bits).

Random-number generation is a complex topic. The Numerical Recipes in C book (see reference above) provides an excellent discussion of practical random-number generation issues in Chapter 7 (Random Numbers).

For a more theoretical discussion which also covers many practical issues in depth, please see Chapter 3 (Random Numbers) in Donald E. Knuth's The Art of Computer Programming, volume 2 (Seminumerical Algorithms), 2nd ed.; Reading, Massachusetts: Addison-Wesley Publishing Company, 1981.

Since I'm picking a random entry from N items, I basically do

n = (int)(((double)rand() / (double)RAND_MAX) * (double)N);

The upshot?

I add an element to the list, the value of N changes, and for a given output of rand() you get a diffent answer than with the previous, smaller N.

And it doesn't matter where I add an item. Add a new occupation for our characters at the end of the list (on the development server) and for plot #1134 you now get:

Sheffie Les Mastenbrook is a mute world-famous inventor from a doomed world. Susette Marie-Jeanne Sanford-Wright is a virginal green-skinned vampire hunter with nothing left to lose. And together, they must defuse a bomb in less than a day that's a thousand miles away.

This “easy feature” is turning out not to be so easy. And this on a simple program. It's stuff like this that makes programming take longer than expected.

The proper solution is to record the fifteen random numbers generated and make that part of the URL, and make sure that additions to the various lists appear at the end, but we finally get “bookmarkable” plots.

Oh, I just realized—only to lose the “bookmarked plots” if the template (and thus, the number of random numbers selected) changes.

Oh, bother.

Wednesday, July 11, 2007

But it will still save on electricity

Even for the crazy world of quantum mechanics, this one is twisted. A quantum computer program has produced an answer without actually running.

This scheme could have an advantage over straightforward quantum computing. “A non-running computer produces fewer errors,” says Hosten. That sentiment should have technophobes nodding enthusiastically.

Via Flares into Darkness, Quantum computer works best switched off

While it's true that a computer turned off produces vast amounts of nothing really fast, so does a burned out light bulb. And the very fact that there's still a program means there are bugs (proof? “Every program has at least one bug and can be shortened by at least one instruction—from which, by induction, one can deduce that every program can be reduced to one instruction which doesn't work.” Q.E.D.”) so it's still far from evident that a non-running quantum computer will have fewer errors than a running quantum computer.

I guess these guys haven't heard of Heisenbugs.


Then again, no two people on any given airplane paid the same amount.

Airplane Tickets

When to Buy: Wednesday morning.
Why: “Most airfare sales are thrown out there on the weekend,” says travel expert Peter Greenberg, a.k.a. The Travel Detective. Other airlines then jump into the game, discounting their own fares and prompting further changes by the first airline. The fares reach their lowest prices late Tuesday or early Wednesday.

Via Flares into Darkness, The Cheapest Days to Buy Certain Items

I know quite a few people who could benefit from this.

Thursday, July 12, 2007

Idiocracy

In Idiocracy, Private Joe Bauers (Luke Wilson) and a prostitute (Maya Rudolph) are part of a secret military project that goes awry and they find themselves 500 years in the future, where the United States of America has been so dumbed down that Joe (with an IQ of 100 in our time) is literally the smartest man in the world.

Past the fart jokes, it's a rather biting satire on our current culture, one of mass marketing, post-literacy and monster truck rallyesque rehabilitation centers. As one reviewer put it:

And if the guffaws don't seem as plentiful as in Judge's previous works, it isn't due to poor quality but rather because each laugh is tempered with the unsettling realization that his vision of mankind's future might not be too far off the mark.

And if you stick around past the credits, there's a small scene that resolves a small, but recurring plot point.

Friday, July 13, 2007

Power

I came across a blurb about a new type of battery that may be used in the national power grid. And I hope it works out (and I'm bearish on this), because power generation is not a trivial thing, as Steven Den Beste lays out in a series of articles he wrote a few years ago (and are well worth reading to get a sense of the immense scale of power generation here in the States):

As Steve says:

If any proposed energy source can't be scaled up to generate 10 gigawatts average (1% of that), it won't be large enough to make any significant difference in the grand scheme of things even if it works and is really, really cool and clever and innovative and nifty.

Obscure Energy Sources

Even though these were written about five years ago, it's still nuclear power that has the best chance of weaning us off expensive carbon-based fuels as a power source.

Saturday, July 14, 2007

Harry Potter and the Order of the Phoenix

Spring, Wlofie and I saw Harry Potter and the Order of the Phoenix. I don't really have much to say about the film—I found it good, so did Wlofie; Spring didn't care for it much, saying the filmmakers had cut a bunch of good bits from the book, and left in a bunch of bad bits from the book. In other words, mixed reviews.

Sunday, July 15, 2007

An analog clock

I've seen several Nixie tube based clocks this past year, but none quite like this Nixie tube clock, which uses only capacitors, resistors, diodes and lamps for the timing circuits.

So I guess you could call this an analog Nixie tube clock.


You know, Mussolini did make the trains run on time …

I INTERVIEWED Michael Moore recently for an upcoming “20/20” special on health care. It's refreshing to interview a leftist who proudly admits he's a leftist. He told me that government should provide “food care” as well as health care and that big government would work if only the right people were in charge.

Via No Looking Backwards, Freedom, benevolence go together

I think what scares me most about this Michael Moore quote is the “would work if only the right people were in charge” bit. I guess only trained professionals know what's right for our lives, and leaving the decision in our hands is right out of the question.


A moving experience, that's for sure

John Deere is helping us steer
Around tight corners in a higher gear
The heavy load of the Church Tower
Just won't move without tractor power

Here it comes!
    (Here it comes! Here it comes!)
Here it comes!
    (Here it comes! Here it comes!)

Via Gates of Vienna, How to move a 100 year old church

It's impressive seeing a church move, but it's the music that makes this video …

Monday, July 16, 2007

Hidden in the books

For only $350, you too can build a secret doorway out of a bookshelf (link via Antarctica Starts Here). Makes me wish I had the space for something like that.


Software wise, we're still in the mid-1980s it seems

Intel first disclosed it had built a prototype 80-core processor during last fall's Intel Developer Forum, when CEO Paul Otellini promised to deliver the chip within five years. The company's researchers have several hurdles to overcome before PCs and servers come with 80-core processors—such as how to connect the chip to memory and how to teach software developers to write programs for it—but the research chip is an important step, Rattner said.

Intel shows off 80-core processor

CPUs capped out a few years ago, leaving companies like Intel and AMD with little recourse but to start stuffing boxes with multiple CPUs. Dual and qual-core systems are common now, even for home computers; how long until the monster above hits the streets?

And it's not just the high end processors that are getting the multicore treatment—even embedded processors are going multicore (link via flutterby).

Progress keeps marching on, but software development hasn't, sadly. Very few languages have parallelizing features, much less automatic parallelization, and multi-threaded programming is still very problematic, with very few languages having it built in.

So, where do we go from here? Well, for a start, some radical ideas about programming languages for one thing …

Tuesday, July 17, 2007

Busy day

Been busy with meetings and research. The meetings I won't bore you with, but the research is interesting.

We have quite a few routers and the number is expected to increase over the next year or so. There was also an incident two weeks ago where I got horribly confused over two T1s and it took a few hours to unravel exactly what addresses got assigned to which T1.

The problem: while I have copies of all the router configurations, I don't have said configurations under revision control, which means I only have a copy of the latest versions. Last week at a meeting, it was brought up that maybe, just maybe, we might want to consider keeping older versions of the configuration files.

There are a number of revision control systems to choose from—CVS, Subversion, darcs, GNU arch, git. Yes, they're primarily used for source code, but any textual data can be historically saved using these systems. So there's no real problem with revision control of the configuration files.

It's also easy to get the configurations off the routers. All our routers support TFTP. It was pretty straightforward to set up a TFTP server on our network to collect all the configurations and to secure it against any unwanted traffic (TFTP is a rather insecure protocol).

The real problem comes in marrying the TFTP server with a revision control system. What I'd like is for the TFTP server to accept the configuration from a router, and immediately dump it into the revision control system. I already have the habit of issuing both write and copy running-config tftp: on the router. I don't really want to have to log into the TFTP server to run revision-control-system-du-jour commit, regardless of how simple it is.

Especially since we're allowing another company to use our TFTP server to backup their routers (it's a partnership thang), and these other people are hard-core Windows users (not that there's anything wrong with that)—I'm sure the last thing they want to think about is logging into a Unix system to issue revision-control-system-du-jour commit.

So I'm looking into modifying an existing TFTP server. You would think that TFTP, a protocol so simple that it takes TCP/IP Illustrated, Volume I: The Protocols, a 576 page behemoth of a book, only five pages to cover, would be a simple program. Even in C. Nope. It's a horribly written maze of #ifdefs and gotos.

Joy.

Wednesday, July 18, 2007

“Energy problem? What energy problem?”

The state of Georgia just granted Range Fuels a permit to create the first cellulosic ethanol plant in America. HECK YES! This is very exciting … why?

Cellulosic ethanol can contain up to 16 times more energy than is required to create it! If that doesn't sound ridiculously impressive, consider that gasoline contains only 5 times more energy than was required to create it and corn ethanol is totally lame, containing only 1.3 times the energy required to create it.

Via Instapundit, Our First Cellulosic Ethanol Plant!!!

It's discoveries and work like this that makes me worry less about “Peak Oil” than most. We're a clever species, we'll work around this problem.


Stupid Twitter Tricks

An off-site meeting was canceled, although I didn't find out about it until I got off-site. Afterwards, I slacked off a bit.

Okay, quite a bit.

I came across this post on one of the blogs I follow, and I was mesmerized. Not by the the actual post but by the often times totally irrellevent picture John Wiseman adds to his posts. And in this case, it's a portion of a screen capture of a Twitter-based site, and John's comment about said picture: “Jenny Holzer is the only person who should be allowed to use Twitter.” Jenny's site reads like surreal fortune cookies, much like the monster quote file I have (over 2,600 quotes).

I've seen Twitter once or twice; enough to get the point of it—it's LiveJournal on crank, but something about Jenny's site reminding me of my own monster quote file inspired me to do a “Stupid Twitter Trick™”—sending out my quote file via Twitter.

Two aspects of this little hack (and that's what it is, a gross hack if you ask me) were time consuming. First, cleaning up my monster quote file. Twitter limits you to 160-character messages (with a preference of 140 characters). Three custom programs for this—one to pull out quotes 160 characters or less (and to mark the 140th character). The second one to trim unwanted spaces. And the third to go through converting the quote character from the unappealing " to the much more typographically nice “” pair. Extensive use of sed to make some other typographical substitutions (such as converting “--” (two dashes) into “—” (a proper em-dash)) and a visual once-over to make sure I didn't muck things up, and an hour or so later, I have almost 2,000 quotes ready for Twitter.

The second time-consuming bit was writing this bit of code, which took about an hour:

#!/usr/bin/perl
use strict;
use Net::Twitter;

my $later   = `./later`;
my $message = `./quote -n`;
my $twit    = Net::Twitter->new(
	username => 'siwisdom' , 
	password => 'XXXXXXXXXXXX');
my $result  = $twit->update($message);

`at -f ./at-jobs $later`;

exit 0;

And no, it didn't take an hour because I'm a slow typist. It took an hour because to install Net::Twitter I needed to install JSON::Any, and in the process of installing that I apparently activated the CPAN module that wanted to install and update itself, and that took an hour (I swear, it seemed to download the entire CPAN archive—sigh).

The later program picks a random amount of time between three and nine hours, which is given to the at command. at is like cron, in that you can schedule a program to run at a particular time, but unlike cron, which runs the program on a set schedule, at is a one-shot deal. I use at because I don't want a set schedule to post quotes to Twitter—I want it randomized a bit. quote is a program I wrote ages ago to pull quotes out of a quote file sequentially.

Like I said, a quick hack for a stupid Twitter trick.

Oh, and the name? “siwisdom”?

It's short for “silicon wisdom,” as a pun on Jorn Barger's Robot Wisdom, if you will.

Thursday, July 19, 2007

Speaking of Bruce Willis films, Hudson Hawk wasn't a bad film either

Chris Tucker should have ended his acting career after The Fifth Element. And not because his other movies suck (though they do), and not because he would prove himself to be an insufferable douchebag (which he has), but rather due to the fact that Ruby Rhod, an intergalactic superstar radio host, was literally the role of Chris Tucker's career.

Via Les Orchard, Real Men Love the Fifth Element

What he said.

And you could do worse than watch The Fifth Element—it's a great film that's fun to watch.


I hate it when I have to troubleshoot the tools required to troubleshoot the actual problem …

I wouldn't call today bad, but it certainly wasn't in the good category either. I had to go troubleshoot a customer network, which was something I wasn't in the mood for. That alone put me in a rather sour mood, and it didn't help things that neither I nor the customer had critical information about the network switches. It took about two hours (and that abomination of a program Microsoft provides called Hyperterminal—and in looking up that link, I find that Microsoft didn't even write that abomination) to secure the information that we should have had (and thus, made me angrier, more at myself than at anything else). Two hours wasted getting to a point where I could actually troubleshoot the original problem.

Sigh.

Friday, July 20, 2007

Email woes

Bunny signed up for my Obligatory Email Notification, and she reported that some of the notifications haven't gotten through. I check, and lo', there are some bounced emails sitting in my inbox:

From
MAILER-DAEMON@conman.org (Mail Delivery System)
To
sean@conman.org
Subject
Undelivered Mail Returned to Sender
Date
Fri, 20 Jul 2007 01:59:42 -0400 (EDT)

This is the Postfix program at host brevard.conman.org.

I'm sorry to have to inform you that your message could not be delivered to one or more recipients. It's attached below.

For further assistance, please send mail to <postmaster>

If you do so, please include this problem report. You can delete your own text from the attached returned message.

The Postfix program

<XXXXXXXX@bellsouth.net>: host gateway-f1.isp.att.net[204.127.217.16] 
    said: 550 [PERMFAIL] bellsouth.net requires valid sender 
    domain {need mx} (in reply to RCPT TO command)

Hmmm … what's this? More bounced emails? To someone else who uses The Monopolistic Phone Company?

<XXXXXXXX@bellsouth.net>: host gateway-f1.isp.att.net[204.127.217.16] 
    said: 550 [PERMFAIL] bellsouth.net requires valid sender 
    domain {need mx} (in reply to RCPT TO command)

Hmmm … same host. Let's see what I get when I toss that host into Google:

Re: RR Notification Bounce

I think RR sent you an email notification (not a member).

bellsouth.net is having issues with reading RR's DNS. I do not know how to contact them. Maybe you could try. Their error message is shown below. No other ISP is having this problem with RR.

RR sent you an email notification. Bellsouth replied back with the following:

<XXXXXXXX@bellsouth.net>: host gateway-f1.isp.att.net[204.127.217.16] 
    said: 550 [PERMFAIL] bellsouth.net requires valid sender 
    domain {need mx} (in reply to RCPT TO command)

Bellsouth had this same kind of problem a while back with Yahoo mail accounts. It took them a while to find and correct the problem but they finally did. It had something to do with a change made to the mail header by Bellsouth's server. If you are a Bellsouth customer, call and make a complaint. Until customers start complaining, they are not likely to work on the problem.

bellsouth.net bounced RR e-mail

Well … how about that? I'm not the only one having problems with The Monopolistic Phone Company.


But on the other hand, wouldn't Snape also know she's a Death Eater?

So, here's the THEORY: Minerva McGonagall is an amazing actress, but she's also deeply and passionately a Death Eater—probably even one of Voldemort's most trusted and loyal followers. As such, she sometimes shows her true colors. Considering her age, she could have known Voldemort during their school days. As a spy for the Death Eaters, it is her job to suck up to Dumbledore. But—unlike Snape—she is highly unwilling to do anything to help the Order. Perhaps she's bidding her time; perhaps she's foiling them more than we know.

So, let's get down to it. Let's painstakingly go through the books and watch McGonagall very carefully.

Minerva McGonagall is Evil: The Ultimate Essay

Having read all the books except the last one (which is just now coming out), I've never given Professor McGonagall much thought in the entire series, but this essay does lay out some good arguments for her being on the side of evil.

It's something to keep in mind …

Saturday, July 21, 2007

Six Words For The Day

Harry Potter and the Deathly Hallows.

Sunday, July 22, 2007

Eight Words For The Day

Talking about Harry Potter and the Deathly Hallows.

Monday, July 23, 2007

Class notes from the School of Hard Knocks

I'm still working on the issue from last Thursday, and I'll note some things I need to remember for next time:

  1. Even if the fault lies at The Customer site, we're still to blame.
  2. Do not close out the trouble ticket with the Monopolistic Phone Company (for they could not find any fault) until the situation is fully resolved, for The Customer (and they will find out) may not understand such actions.
  3. Do not taunt the Happy Fun Dan.

And the way things are going, it looks like I may be working on this issue all week.

Friday, July 27, 2007

I never did handle stress well

It pretty much took all week.

Well, at least until Thursday o'dark-thirty.

From what we can tell, there was a lightning strike at or near the customer site, which took out all four of their T1s (two data, which terminate at our Data Center, and two voice, which I suppose terminate somewhere within the bowels of The Monopolistic Phone Company). The Monopolistic Phone Company did eventually come out and replace all four smart jacks at the customer location (as well as the container box). Then I spent a few days playing Musical Equipment trying to get everything back up and running (let's see, we replaced nearly all the cables, one CSU/DSU, a router and a firewall).

It was a very frustrating week, let me tell you.

Lessons learned this time:

  1. The problem is not what you think it is.
  2. It never hurts to double check what you think is correct.
  3. It ain't over until the fat server hums.
  4. Thank God I wasn't drunk.

I then called in sick yesterday and spent the entire day sleeping.


Our customer wasn't the only thing down this week …

Now, about that last lesson

I don't get drunk, but I do tend to get rather agitated when under pressure [that statement alone should win “Understatement of the Year” Award. —Editor], and I'm surprised there wasn't more collateral damage [where ever you got those racks from, Smirk, keep them. They take a lot of abuse. —Editor].

There's also no real evidence that was a drunk employee took down 1/3 of the Internet earlier this week. Apparently, it was major power outtage in San Fransciso coupled with a massive backup generator failure that took out 1/3 of the Internet earlier this week (link via Flutterby).


Coca Cola and jam butties

Londoner Luke Bream, 33, sporting a pink and white jersey, is attacking a punishing mountain leg of the world's most famous cycle race, the Tour de France. It is clearly hard going.

At least he is well in front of the 152 remaining riders (189 set off from London) in the three-week long Tour. In fact, he is 24 hours ahead as he has been along the entire route so far.

And amid the backdrop of accusations of cheating among official Tour de France riders, [his mother] assures the Guardian Luke is on nothing but his own adrenaline.

“Oh no, Luke doesn't take drugs at the best of times, not even an aspirin if he has a headache. He does take some cod liver oil tablets, but apart from that he's doing this largely on Coca Cola and jam butties.”

Via Flutterby, The Englishman who is leading the Tour de France

For Wlofie, who might get a kick out of this …

Update on Tuesday, July 31st, 2007

The Englishman won (link via Flutterby).


Life at Casa New Jersey via snippits of email

From
Spring Dew <XXXXXXXXXXXXXXXXXXX>
To
<sean@conman.org>
Subject
news and stuff
Date
Fri, 27 Jul 2007 12:11:18 -0400

Electrical repairs this weekend whenever we can coordinate to have the machines down. On the list:

I think that's it. Questions, ideas, comments, complaints?

From
Sean Conner <sean@conman.org>
To
Spring Dew <XXXXXXXXXXXXXXXXXXX>
Subject
Re: news and stuff
Date
Fri, 27 Jul 2007 17:16:58 -0400

I think that's it. Questions, ideas, comments, complaints?

  1. Why is the sky blue?
  2. How about we feed mayonnaise to tuna fish?
  3. I have a red pencil.
  4. I hate our customers.
From
Spring Dew <XXXXXXXXXXXXXXXXXXX>
To
<sean@conman.org>
Subject
Re: news and stuff
Date
Fri, 27 Jul 2007 17:23:35 -0400
  1. Refraction.
  2. It won't help. It'll just become mayo-poop in the bottom of the ocean.
  3. Congratulations.
  4. Me too.

Email woes II

Bunny spent the past few days berating The Monopolistic Phone Company about their little email problem. It seems to be cleared up for the most part, except for the occasional:

Final-Recipient
rfc822;XXXXXXXXXXXXXXXXXXXXXX
Action
failed
Status
5.0.0 (permanent failure)
Diagnostic-Code
smtp; 5.1.0 - Unknown address error 502-'Command not implemented' (delivery attempts: 0)
Reporting-MTA
dns; mx00.mail.bellsouth.net

And in checking the MX record for The Monopolistic Phone Company, I have a 1 in 3 chance of hitting the bad server there.

Lovely.


Why yes, I am making up for lost entries this week. Why do you ask?

I just came across two computers, one rather silly, and one rather cool.


My Life, not with the Thrill Kill Kult, but with the Monopolistic Phone Company

Lovely.

Wlofie reported that some thing (animal or mechanical) knocked the phone cable leading to Casa New Jersey right down, and that the Monopolistic Phone Company said it may be as late as Monday before the new shipments of round toits come in.

Sigh.

Saturday, July 28, 2007

With a large enough hammer, anything will fit!

It's been a busy day.

I dropped Bunny off at the airport (she's flying out to Seattle to visit family) and by the time I got back to Casa New Jersey, Spring had all the supplies for all the electrical work that needs done about the house.

The light switches (there were two being replaced) went quickly. The back porch light fixture replacement was fairly straightforward, and thankfully, the wasp nest inside had long been abandoned.

[These bastards didn't even have the courtesy to pay rent!]

I can't say the same about the bathroom fan.

The fan unit itself came right out. So did the fan unit outlet. The fan unit housing, on the other hand, required the application of a few screw drivers (one mangled beyond use), a large hammer, a crowbar, and some cringe-worthy damage along the ceiling before it was finally extracted whereupon we found the second wasp nest of the day:

[Another colony of freeloaders]

And much like the other one, this one had (thank God!) been abandoned as well.

It was much to our disappointment that the replacement fan was ¼″ too large to fit.

Sigh.

Meanwhile, The Monopolistic Phone Company found some round toits and managed to roll a truck out our way. Bob, The Monopolistic Phone Company Technician got right to work on restoring our phone service. By the time Spring and I realized the bathroom fan unit we had wouldn't fit, Bob had finished connecting up our phone system and was going nuts trying to figure out why the DSL wasn't working. We told Bob that the DSL was off, since we flipped all the breakers.

But we did test the phone at least, and it was working. So the DSL should (there's that word again) come up when we restored power. Bob left.

We also left. Spring and I headed over to Home Depot to see if we could get a bathroom fan that would fit.

We got there only to find out we were screwed. All the units were the same size, meaning they were ¼″ too large. Actually, it was the fan unit housing that was ¼″ too large—the fan unit itself would (just barely) fit. After spending some time thinking about it, we decided to keep the unit we had, and using some tin snips (which we purchased), cut the housing to fit.

And by God we got that fan unit to fit. I cut a quater inch off the fan housing (basically, we removed one whole side), shove it into the space, then with the application of a large hammer, somewhat forced the fan unit itself into place (it was a very tight fit).

And by God if it didn't work too!

Woot!

And we have Intarwebs again!

Double woot!

Sunday, July 29, 2007

You know, if my Page Rank™ wasn't so high, I probably wouldn't have to do this. Ah, the price of fame …

I decided to scrap the Obligatory Email Notification here at The Boston Diaries. I modified the script a few months ago to record the nefarious abuses of that script, and now, I've decided that enough is enough. The only people who are using abusing the script (and there are currently 200 or so fake requests awaiting verification) are spammers (especially this past month—the crap I've seen being submitted makes me think it's related to a rather sophisticated spamming attack).

Now, I haven't scrapped the email notification entirely—all who are currently subscribed (all six of you) will still receive email notifications of updates here, but I'm not accepting any new signups.

And I've gone ahead and replaced the Obligatory Email Notification section of the sidebar with Obligatory Twitter Updates—updates from my stupid Twitter trick from a few days ago. Because, you know, you can never have too much extraneous crap cluttering up the blog.

Monday, July 30, 2007

Actually, I've gotten over the cravings and now wish to divest myself of these classic computers

Sean Conner, a collector and network administrator from Lake Worth, agrees that older computers are ideal to learn on.

“The older a computer is, the easier it is to understand,” he said. “You can crack open my first color computer [Jamie Malernee probably didn't know to capitalize Color Computer —Editor] and say, ‘Here is the CPU [Central Processing Unit], there's the memory— here's how it all works.’ On a modern system, they're just monsters.”

That isn't why he is a collector. Conner prefers older systems for their quirks and bold forays into the unknown. For instance, a computer called the Amiga, made by a now-defunct company named Commodore, had video and music editing capabilities in 1985, a full decade ahead of IBM's Personal Computer, he said. But demand for the computer died because it wasn't advertised enough and customers thought IBM computers were more practical for business needs, he said. “There are products from 10, 20 years ago that failed, but maybe it was because they were too early [for their time], or it wasn't marketed enough, or because it was bundled with other products that were a dead-end,” Conner said.

S. Fla. computer collectors crave vintage hardware

Back in April, a call for Classic Computer collectors who lived in South Florida went out on the Classic Computers Mailing List, and I was one (I think the only one) who responded. I was then given the contact information for Jamie Malernee, the reporter, and she interviewed me over the phone (a few times in fact).

As reporting goes, this is pretty fluffy, but the basic information is correct, if sparse.


A satirical look at satire. Or is it?

While at the grocery store, I mentioned to Wlofie that the Week ly World News was closing down (you know, the “newspaper” that reported about Bat Boy). We then got into a conversation about other satirical newspapers that were having problems these days, but is it any wonder why?

Do you know Cory Mashburn and Ryan Cornelison?

If you do, don't approach them. Call 911 and order up a SWAT team. They're believed to be in the vicinity of McMinnville, Ore., where they're a clear and present danger to the community. Mashburn and Cornelison were recently charged with five counts of felony sexual abuse, and District Attorney Bradley Berry has pledged to have them registered for life as sex offenders.

Oh, by the way, the defendants are in the seventh grade.

Swat somebody's butt, and yours belongs to the the D.A.

Where can satire go after that?

I ask you? Is this satire? Or real?

What is a nerd? Mary Bucholtz, a linguist at the University of California, Santa Barbara, has been working on the question for the last 12 years. She has gone to high schools and colleges, mainly in California, and asked students from different crowds to think about the idea of nerdiness and who among their peers should be considered a nerd; students have also “reported” themselves. Nerdiness, she has concluded, is largely a matter of racially tinged behavior. People who are considered nerds tend to act in ways that are, as she puts it, “hyperwhite.”

And what about this?

During the 40-minute speech, Bush also promised to bring an end to the severe war drought that plagued the nation under Clinton, assuring citizens that the U.S. will engage in at least one Gulf War-level armed conflict in the next four years.

“You better believe we're going to mix it up with somebody at some point during my administration,” said Bush, who plans a 250 percent boost in military spending. “Unlike my predecessor, I am fully committed to putting soldiers in battle situations. Otherwise, what is the point of even having a military?”

I hate to say this, but the second quote, written in January of 2001, is supposedly satire while the first quote, written yesterday, is supposedly not.

How can The Onion compete with 12-year long studies on nerdom?

Okay, one more example, this time, about the Sultan of Brunei's private airplane:

What happened to his private, luxurious A-340 or B-777 (all decked out with gold poopers and seating for ten people)?

It's in the shop being remodeled. The poopers are now being replaced with swiveling models that can be turned to face away from Mecca when the plane is on certain routes. Until now the plane often had to change course during pooping, which led to trouble with the aviation authorities.

True, or false?

A few years ago, I would have said that's just plain silly. But now? What with Canad ians complaining about their health care system and English kids looking up to Hitler, reality is giving satire a really good run for its money.

And given how Muslims are touchy about their religion, I can easily see the Sultan installing swiveling toilets in his plane. But in reality, it's not clear if it's true or not.

Which, I guess, is the best that satire can do these days.

Tuesday, July 31, 2007

Going once … going twice …

After The Company meeting today, we ran into RW, a customer of ours. He mentioned in passing that a major domain name auction is happening tomorrow, and did we have any domains we might want to auction. Smirk had a few, and then I remembered one I have—pornfinity.com.

I had registered it years ago for a project that never materialized. Then a few years later I thought of another project it could be used for, but I took too long in getting it set up and the window of opportunity passed.

RW liked the name, and asked what I would like for it. I said $5,000. If I don't hear anything back in a few days, I'll assume the price was too high. Hey, it can't hurt to try, right?


Stupid CSS tricks

I thought of maybe trying to spruce up Pornfinity to maybe make it more attractive at auction (and no, I didn't spruce it up—I got distracted as you'll see) by adding some links or something.

I wanted to do a bit more than just present a simple list of sites. I mean, sure, I could do something like:

(And no, these aren't porn sites, these are blogs that I read. I'm using them for an example. If you want porn, you'll have to go on your own and find some)

A lot of sites now have a favicon so I thought it might be nice to include them with the links (yes, that's the extent of my “snazzing up” the list of porn sites). So, first off, is it possible to change the default glyph used for lists?

The answer: yes. By using the CSS attribute list-style-image, you can have custom bullet points.

Now, I have noticed that Firefox will store the favicon when you bookmark a site. Curious as to where that information was stored (if I already have the data (and yes, I do have one or several dozen porn sites bookmarked—ahem) why bother re-downloading it all again?), I found that Firefox stored the data in a rather curious looking URLthe data: scheme.

Hmmm … I wonder … would this work?

<li style="list-style-image: url(data:image/x-icon;base64,AAAB...A==);">
  <a href="http://www.flutterby.com/">Flutterby!</a>
</li>

Well … what do you know? It works:

Well, probably not under Microsoft Internet Explorer, but I don't care about that browser.

Pretty neat trick, actually.

Well … I thought it was anyway.

Wednesday, August 01, 2007

I also think he'd be pissed that his image is being sold for profit by eeeeeeeeeevil Capitalists

Cybercast News Service: What sort of policies was Che implementing?

Humberto Fontova: Massive nationalization. Rene Dumont, a French socialist economist, went to Cuba to advise the regime and told them, good grief, you've done more radicalization, more nationalization in two years than the Chinese revolution did in eight years. They were nationalizing everything, stealing all private property, turning farms into state farms— and that naturally would get rid of any potential capitalist rival. This was accomplished by 1964-65. And Che Guevara had made such a mess of it, the Soviets told Castro “enough!” They told him to remove Che Guevara, to lay him off, do something else with him. The Soviet Union poured the equivalent of eight Marshall Plans into Cuba. Think about it: One Marshall Plan, $9 billion, sent to war-raved Europe with 300 million people, and it worked. Eight of these plans, $72 billion, sent to Cuba, a country of 6.5 million people, who formerly had a better per capita income than half of Europe, and the place is poorer than Haiti today. That defies not just the laws of economics but also the laws of physics.

Via Instapundit, ‘Cool’ Icon Che Guevara Was a Murderous Thug, Author Says

Nothing much else to say except for “read the whole thing.”

Thursday, August 02, 2007

Ugh

Not much to say today—have a rather long to-do list, one item of which involves OpenGroupWare and installing is as easy as:

TODO: write configuration guide for OGo 1.1

(and that's not just the high level overview of the configuration, that is all the documentation for configuration—and no, I didn't get it running)

It's also not helping that I have a terrible headache.

Ugh.

Friday, August 03, 2007

This is way better than just feeding mayonnaise to tuna fish

When I came across the world's quickest electric motocycle (link via Flutterby) that can do 0–60 in one second and the ¼ mile in 8, I thought of Gregory, but I'm not sure why. Gregory isn't the crotch-rocket type of guy.

Then I had an idea: the X-Prize guys have it all wrong! They shouldn't be rewarding a more efficient gas-powered car. No—they should be sponsoring an all-electric car race!

Think of it—the Electric Daytona 500! The only limitation—the vehicle has to be powered solely by electrons. No other restrictions on size, weight or shape. The first past the checkered flag after 500 laps wins the prize. Make it an annual event, and I guarentee you'll see rapid electric car innovations.

Saturday, August 04, 2007

A noisy melancholy

It was a rather long two months that ended today with the return of The Kids.

Sigh.

There goes the quiet.

Sunday, August 05, 2007

A reverse captcha

Several months ago I added a hidden field to my Email Notification Signup form (and later, renamed the script to flush out any spammers that cached the script location) and boy, was I getting spammed through that script.

The thought of using such a techique as a reverse captcha never occured to me. Hiding a form element such that normal users won't see it, but spambots will, and rejecting any request with that field filled in. What a neat idea.

Of course, that's assuming I ever get around to having comments on my blog …

Monday, August 06, 2007

Development work for a change

Mark hired me to do some work on Seminole, his embedded web server. I'm finding it a difficult thing to work on—not because the code is bad, but because the code is in a language I'm not comfortable programming in (C++) in an environment I'm not used to (embedded programming) and I'm weak in reading and understanding the code of others.

It could be worse though—I could be making performance enhancements to osCommerce.

It's also got me thinking about the whole development process. On how we write code, edit code, compile code and store code. About multiple development branches (Seminole currently has 21 compilation targets and 34 compile time selectable options). And language design, because I think that how we develop code influences computer language design.

Update on Wednesday, August 8th, 2007

Mark had some comments about this entry:

  • You misspelled “language” twice on your blog post. [Fixed. This is something that happens too often, actually. —Editor]
  • You may want to mention I didn't choose C++ either. It chose me when Seminole was “accidentally” created. [True—but that's a story for Mark to tell, not I —Editor]
  • There are way more than 21 compilation targets. What you see is the “in tree” reference portability layers. I have a few customers who have created their own.
  • You may want to go to a Barnes & Noble and check out a book from O'Reilly (no animal on the cover though) called Beautiful Code. I just bought it but haven't had a chance to read through.

Tuesday, August 07, 2007

“And now the fighting begins … followed by a light salad.”

Nothing quite like waking up to clothes and knapsacks flying down the stairs, followed shortly by two Kids flying down the stairs amid cries of “S'not!” and “Is!”

Three days. Frankly, I'm not sure if I should be thankful the quiet lasted this long, or upset that it didn't last longer.

In any case, things have been resolved, clothes and knapsacks cleaned up and life has gone quiet again for the time being (and in case you're reading this Spring—they woke me up must mere moments before the alarm would have, and whatever fight they were having has long since been forgotten).


Gollum sings

I never thought I'd say that Gollum is cute, but he is when he's singing “You're Beautiful” to his ring.

Wednesday, August 08, 2007

Not going at all …

Since I haven't heard back about the auction, and I still own the domain in question, it seems that my offer of $5,000 was a bit too much for it.

Ah well, didn't hurt to try.


Snippits of an overheard conversation at Lester's Diner around 11:30 pm

“My niece only has to get past a background check before she can get her dream job with the government. The only thing she's worried about is her credit score.”

“Credit score? For a background check?”

“Yes, credit score.”

“I thought a background check for a government job was stuff like criminal records, school records, getting character references, not a credit check.”

“Before I got hired by the government, my credit was checked.”

“Bizarre.”

“Well, people who are in financial trouble are more susceptible to bribery.”

“So if you get hired by the government, you undergo a credit check, but not if you get elected?”

“Yup, I guess that's how it works.”

Thursday, August 09, 2007

Stupid date tricks

Oooh, look! It's 07-08-09!

Okay, it's 2007-08-09, and yes, not many people write the two-digit year first.

That's why this is a stupid date trick.


Books that don't exist

Programming Small Devices

This book's aim is to help students who have been spoiled by gigabytes of RAM and gigahertz processors deal with the harsher, leaner world of small devices. Like Müldner's C for Java Programmers, it assumes readers already know how to program, and focuses on dispelling their misconceptions and curing their sloppy habits. What do you do when you don't have garbage collection? What do you do when you don't even have floating point, or when you have to worry about watts as well as bytes? Ranging over architecture, basic data structures, and neat programming tricks, this is an excellent introduction to programming in a world where nothing is free.

Programming Small Devices—Not on the Shelves

I could probably use a book like this, as long as it also covered compiling and linking issues one finds in embedded systems programming.

But alas, that book does not exist. Along with seventeen other interesting books that don't exist, but should (too bad too—Error Handling is something that needs to be taught, and isn't—I actually had a university teacher tell me, “If you don't know how to handle the error, don't check for it,” and that's pretty much the only thing I was “taught” about error handling in college).

Friday, August 10, 2007

The climate may or may not be heating up, but the debate sure is

NASA has now silently released corrected figures, and the changes are truly astounding. The warmest year on record is now 1934. 1998 (long trumpeted by the media as record-breaking) moves to second place. 1921 takes third. In fact, 5 of the 10 warmest years on record now all occur before World War II. Anthony Watts has put the new data in chart form, along with a more detailed summary of the events.

Via Flut terby, Blogger Finds Y2K Bug in NASA Climate Data

If the article isn't enough to show we still don't know enough about the weather to make dire predictions, then the scores of comments should be enough, with both sides debating the various arguments (“Greenland is melting!” “But it's also revealing large Viking settlements showing it was warmer a millenium ago!”).

Saturday, August 11, 2007

The next breakout videogame-to-movie movie

Sure, there have been plenty of video games turned into Hollywood lacklusters, such as Doom, Final Fantasy, Mortal Combat and Super Mario Brothers. But those will pale in comparison to Minesweeper: The Movie (link via kisrael.com).

Sunday, August 12, 2007

While the Bible might be the literal Word of God, it would have behooved Him to have created Xerox a bit sooner than He did.

My calligraphy has gotten to the point where I'm now doing actual illuminated (illustrated) pieces (although other people do the illumination—I just add the lettering). The main problem I have now is that the writing is so slow that it's very easy to make a mistake.

In fact, I made two mistakes on the piece I just finished.

Mistake number one: I was supposed to write “whose continued and exemplary service as a chirurgeon has brought comfort to so many.” But in going so slow, I wasn't paying attention to what I was actually lettering, and wrote instead “whose continued and exemplary service to so m” before realizing my mistake.

Oops.

Not having a small knife to scrape the mistake away (nor even the more modern Liquid Paper™) I decided to carry on and rewrite that particular sentence to read “whose continued and exemplary service to so many as a chirurgeon has brought comfort.”

Okay, so not the best wording, but when it's hard (or impossible) to fix mistakes, you roll with it.

Mistake number two: the word was supposed to be “Companion” but I had just finished writing “Ch” when I realized it wasn't supposed to be “Champion.”

Oops.

It's “Champion” now. Hope that's okay.

Who would have thought that going so slow would be so error prone?


Data mining for fun and profit

TRENTON, N.J.—Adulterers, beware: Your cheatin' heart might be exposed by E-ZPass. E-ZPass and other electronic toll collection systems are emerging as a powerful means of proving infidelity. That's because when your spouse doesn't know where you've been, E-ZPass does.

Of the 12 states in the Northeast and Midwest that are part of the E- ZPass system, agencies in seven states provide electronic toll information in response to court orders in criminal and civil cases, including divorces, according to an Associated Press survey.

Via Instapundit, Toll records trip up philanderers

I wonder how long it will be before they start mailing out speeding tickets based upon transit times between toll booths? The information is there after all …

Monday, August 13, 2007

“You are in a twisty maze of passages, all alike … ”

Accordingly, this paper analyzes previously unpublished files recovered from a backup of Woods's student account at Stanford, and documents an excursion to the real Colossal Cave in Kentucky in 2005. In addition, new interviews with Crowther, Woods, and their associates (particularly members of Crowther's family) provide new insights on the precise nature of Woods's significant contributions. Real locations in the cave and several artifacts (such as an iron rod and an axe head) correspond to their representation in Crowther's version …

Via Flutterby, Somewhere Nearby is Colossal Cave: Examining Will Crowther's Original “Adventure” in Code and in Kentucky

I remember first “playing” this game in 5th Grade (where “playing” involved the teacher reading the descriptions off the only Apple ][ in the school, asking us elementary students what to do next, and typing in the directions given) but it was later, in high school, when my friend Bill and I would play this game for hours (on his family's IBM PC), and I can still picture the map Bill made as we made our way through the game.

What's interesting about this report are the actual photographs from the cave system that show up in Adventure.

Fortunately (or unfortunately, depending upon your take), there are no pictures of a grue—I guess the flashbulb scared him off.


Ramblings about search engine optimizations and bandwidth utilization

For the past week or so, I've been playing around with search engine optimizations (that last link is so I know what not to do) and poring through the log files.

The last time I made a major search engine optimization to my site was four years ago, and the reason for that optimization was to get rid of the disturbing search requests that were plaguing the log files (and my mind) at the time. It also had the added benefit of reducing the amount of “duplicate content” on my site. A search engine like Google would skip indexing the monthly archives (as well as the front page) but would index the individual entries. The end result: no more disturbing search requests, and better results for people actually looking for stuff.

But it didn't reduce all the duplicate content. There was still the small problem of /2000/1/1.1 having the same content as /2000/01/01.1 (note the leading zeros). Technically, they are two separate pages, each with a unique URL, although internally, the leading zero is ignored by my blogging engine and it would happily serve up the page under either location.

Now, that particular duplicate content issue is something I've known about since I started writing mod_blog and I had code to distinquish between the two requests, but never wrote the code to do anything about it. Until last week. Now, go to /2000/1/1.1 and you'll get a permanent redirect to /2000/01/01.1. This change should further reduce the amount of “duplicate content” on my site, as well as reduce the number of hits from web spiders indexing my site (although the redirection doesn't happen under a very unique condition, but fixing that pretty much requires a complete overhaul of some very old code, but it's such a seldom used bit of code that I'm not terribly worried about it).

I'm a bit concerned about the spiders because of some other information I've pulled out from the log files. My archive of log files (at least, of this blog) go back to October of 2001 and using some homegrown tools, I generated (with the help of GNUPlot) this graph of the growth of my site over the past six years:

[Graph of traffic growth at The Boston Diaries]

In red, you see the number of raw hits to this site (with the scale along the left hand side), with some explosive growth in early 2006 and again in just the last few months here. In green you see the actual bytes transferred (with its scale along the right hand side)—pretty steady up until January of 2006 when it goes vertical, and again it goes vertical in just the past few months.

And I'm at a loss to the sudden explosion of bandwidth usage in my site. Unless it's a lot of people hot linking to images on this site (and yes, that does happen quite often), or a vast increase in the number of spiders indexing my site (and for the past few months, Yahoo's Slurp has been generating about 40,000 hits a month).

I may no longer have disturbing search requests, but I know have a disturbing use of bandwidth.

Tuesday, August 14, 2007

And here I thought my bandwidth drop in mid-2002 was due to implementing an RSS feed for my site

I did a bit more probing of my webstats and located when my bandwidth shot up—February 22nd 2006:

Bandwidth increase
Date Bytes Hits Status
Okay (200) Redirects (300) Client errors (400) Server errors (500)
02-19-0612,167,3342,2402,075163 2 0
02-20-0611,955,3752,0171,863151 3 0
02-21-0612,511,2102,3722,197173 2 0
02-22-0656,693,8392,1451,79213713203
02-23-0645,939,3571,7371,563152 5 17

I checked the logs on the on the 21st and 22nd, and for some odd reason, Apache didn't bother logging the bytes transferred on the 21st (and prior) but did starting on the 22nd (and afterwards). I switched servers in February of this year so that's not the explanation—perhaps I upgraded Apache that month or something (since most of the pages served up on this domain are done via a CGI script, it looked like Apache didn't bother to track the amount of data served in that case, and later versions do).

That might also explain the drop in bandwidth around July/August of 2002—I might have upgraded Apache then and that particular version didn't record the bytes sent via a script properly. So basically, the bandwidth metric is useless between July 2002 and February 2006.

Not that I'm overly concerned about it—it was more curiosity than anything else (and if need be, I could reconstruct the data since I have versions of previous templates used, but there's no need).

Also contributing to the spike in early 2006 are actual traffic spikes that happened in April of 2007, like here:

Bandwith Spike
Date Bytes Hits Status
Okay (200) Redirects (300) Client errors (400) Server errors (500)
03-31-06 49,231,7681,9771,771196 82
04-01-06148,802,6025,4425,233171380
04-02-06 59,528,1602,1972,030164 21

But those are more easily explained as simply more hits.

Wednesday, August 15, 2007

Great! Future civilizations will come to the conclusion that Woody Woodpecker destroyed ours.

“What are you doing here?” they asked.

They were construction foremen, superintendents and project managers attending a course in construction planning from the Lean Construction Institute (LCI). Indeed, what was I doing there?

I started to explain: “In software development, we are told we should manage our projects like construction projects, where a building is designed at the start, cost and schedule are predictable, and customers get what they expect.”

Silence. “You're kidding, right?” “No, honest, that's what we're told.”

Incredulity turns to laughter. The idea that programmers would want to manage projects like the construction industry strikes my classmates as ludicrous.

Via Flutterby, Lean Construction

There's an old programming joke: “If builders built buildings the way programmers write programs, the first woodpecker that came along would destroy civilization.” It sounds like it may not be that much of a joke any more …


“Michelin—Tastes so good cats ask for it by name.”

Mark just sent me a link to Logomotto, a silly page that mixes a randomly selected logo with a randomly selected motto (just now I got the Homeland Security logo with the motto “Can you hear me now?”).

Thursday, August 16, 2007

Notes on an anti-spam system

At the weekly meeting the other day, Smirk asked me to look into some alternative anti-spam measures, since more and more spam is making it past the spam firewall. I mentioned the success of greylisting and he told me to look into it.

I've currently downloaded several packages for both Sendmail (what we use at The Office) and Postfix (what I personally use) and there's better support for greylisting now than there was three years ago, but I'm rather puzzled that all the implementations so far use some form of database backend to keep track of all the requests (tumgreyspf uses the filesystem, but as Mark likes to point out, that's a form of database) when one could just as easily keep track of the requests in memory.

It's not like we're stuck with 256M of RAM these days. Even on my Mac mini, the resident set size of Firefox is 16M and I figure you could store about 65,000 requests (which would be swept clean every hour anyway) in 16M.

So my plan is to write some greylist software that keeps everything in memory, so it should be fast, with no worries about resource exhaustion. The protocol used in Postfix is easy, and I can cannibalize code from two previous daemons I wrote to get up and running rather quickly.


Hey, they have a hard enough time predicting the weather ten days from now. What makes you think they can get it right a century from now?

D.C. resident John Lockwood was conducting research at the Library of Congress and came across an intriguing Page 2 headline in the Nov. 2, XXXX edition of The Washington Post: “Arctic Ocean Getting Warm; Seals Vanish and Icebergs Melt.”

Via Instapundit, Bef ore Gore

The article in question was written before Al Gore became famous for Global Warming. In fact, the article in question was written before Al Gore was even Vice- President. The kicker?

It was dated November 2, 1922!

Sad to say, but the East Coast is still here.

Friday, August 17, 2007

An offer I can't refuse?

There's nothing quite like checking your email and finding one from a large software company that dominates its field asking if you would consider a position at said company.

Just like that. Right out of left field (or is it “left out of right field”?).

Okay, part of it was based upon AMC, which is a project Mark wrote (and yes, I do host it) but also mentioned was mod_litbook, which I wrote.

I forwarded the email to Mark on the off-chance he didn't get it. I also replied to the email. I'm curious to see what happens.

Saturday, August 18, 2007

I think I'll go crawl into bed now

Not only did I lose everything related to my Stupid Twitter Project due to a misplaced rm command (and that was due to a misunderstanding on my part of how git works, which is another rant for another time), but I also found out why the graylist implementations (at least under Postfix) use a database backend—because except for the “master programmers” who wrote Postfix, externally written software by us mere peons is so bloody buggy that any external programs are only run once—or in other words, each incoming email spawns yet another process to do the graylist check.

Sigh.

Either I go with a database backed graylist program, or I create an additional shim piece of software to connect to the daemon I just finished.

I swear our industry rewards Rube Goldberg contraptions programming.

And to even further demoralize me, writing this entry revealed a rather bad display bug in mod_blog, which was introduced when I made a few changes the other day.


You'd think that after sixteen years someone would have fixed this problem by now.

I'm also getting pissed off that Linux and X-Windows can't seem to agree on what the Backspace character is supposed to be.

Sunday, August 19, 2007

More notes on an anti-spam system

Sometimes, a setback is just what we need to clear our minds and rethink the problem.

Postfix and Sendmail handle external policy checkers differently (and I assume Qmail handles them differently as well).

The solution?

Write the Postfix and Sendmail policy checkers to talk to a long-lived graylist daemon, which should simplify things quite a bit.

Now that I've decyphered the Postfix protocol (it's only when you check the example graylist server that you find some critical information not mentioned in the documentation—sheesh) things should go a bit more smoothly.

Monday, August 20, 2007

Progress

It was a fairly productive day today, despite waking up feeling like death warmed over. I've pretty much recovered from Friday night's meltdown—my Stupid Twitter Project is back up and running and I fixed the rather bad display bug in mod_blog (that was just a one-line fix).

Work on the graylist program continues, albeit at a slow pace. While working on it, I discovered that some library code I wrote (which is basically a replacement for ANSI C's stdio.h) has problems with the whole “end of file” concept. While that sounds bad, it's not, because the whole concept of “end of file” under Unix is rather undefined. Normally, you detect the “end of file” under Unix by calling read() and if you get back 0 bytes, then you can assume there's nothing more of the file to read—you've reached the “end of file.”

But depending upon how things are set, and what type of device is the target of the read() call, getting back 0 bytes doesn't necessarily mean there's nothing more to read. It just means there's nothing more to read right now.

That, coupled with the fact that you can't normally detect “end of file” without actually trying to read the file (if in fact, it is a file) means that having a function to check to see if you are at “end of file ” (like feof()) is a rather difficult thing to get correct (which gets around to the question of why I felt it was necessary to write my own replacement for stdio.h—because I needed the ability to treat strings as files and you don't get that under stdio.h).

I'm hoping to get the initial version of the graylist software up and running in the next few days.

Tuesday, August 21, 2007

Work

Work continues on the graylist program. I'm working on the Postfix interface for my own domain, and Smirk just mentioned a domain we can use to test the Sendmail interface. Smirk's domain is perfect for testing because

  1. it's been around for twelve years;
  2. it was a heavily used domain (in terms of email) up to around the turn of the century;
  3. it's not currently used for anything.

So the domain in question gets nothing but 100% spam (and a lot of it, according to Smirk)—perfect for testing the filtering capability of a graylist.

Thursday, August 23, 2007

Quick update before I pass out again

Ick. Sick. Cold. Hate.

Blah.

Monday, August 27, 2007

Back from the Dead

Hi.

I'm back among the land of the living, having finally kicked the cold, although it wasn't a plesant experience, let me tell you. Once I felt the cold settling in my lungs, I knew that if I didn't do something, the term “antibiotics” would soon be bandied about, along with “emergency room,” “deductable” and “bend over, this won't hurt at all.”

Yes, it was cough syrup time.

My hand written notes during Saturday (or was it Friday night?) are a bit tough to make out, but let's see …

“If you drink without rythm, you won't attract the worm.”

I feel like a cross between Hunter S. Thompson and Christopher Walken.

And it devolves from there, amid a margin filled with bizarre doodles. I'm thinking the bit about the worm was related to this video. At least, I hope it was related to that video because the very idea of a mashup between Dune, Fear and Loathing in Las Vegas and Brainstorm is too frightening to consider.

After I admitted to Spring that I felt like Carlos Castaneda she suggested I seriously cut back on the cough syrup.

By late Sunday I was feeling much better.

But my blogging software wasn't


And my blog's back from the dead as well

I was curious if my efforts at fixing some issues with my blogging software were having any affect. So I checked the current server logs and yes, my efforts did have an affect:

Slow death of a blogging engine
Site Bytes Hits Status
Okay (200) Redirects (300) Client errors (400) Server errors (500)
boston.conman.org 3,050,415,479 130,912 99,696 24,403 935 5,876

And some significantly bad affects if that last column is anything to go by (which were the number of requests that the server could not handle due to an internal problem, like my blogging software crashing).

Upon initial investigations, it appeared the problem was lost data—my program was generating output, but it wasn't getting to Apache. That's a buffering problem, and an easily fixed one (I just have to make sure that before my program ends, any data it has buffered is written out). But that didn't fix all the problems.

If anything, the problems were getting worse.

And they seemed to be smack dab in the middle of the actual blogging engine itself—a bit of code that I haven't really touched in six years. Mainly because I didn't want to touch this code. It was ugly. Convoluted. Comments like:

/*------------------------------------------------------------
; adjustments for partial days.  The code is ugly because
; of the reverse hacks I've done without really understanding
; how I actually *implemented* the reverse display of entries.
; Funny how I'm the one writting the code and even *I* don't
; fully understand what I'm doing here. 8-)
;-------------------------------------------------------------*/
and
/*----------------------------------------------------
; I have no idea how long ago I wrote this code, but in
; all that time, I never knew that blog->stentry or
; blog->endentry could become negative.  It didn't seem
; to affect the rest of the code, but with the new adtag
; feature, it became a problem.  This bit o' code ensures
; that they at least remain positive.  
;
; I still don't fully understand what I'm doing here.
;--------------------------------------------------------*/

litter the code. And to top it all off, the reverse printing of entries never fully worked right. The more I hacked on the code to get it right, the more I came to realize—

I'm going to have to scrap this mess and rewrite it from the ground up (well, not the entire program—just the portion that deals with collecting up the entries and displaying them, which works out to be about half the code).

The code is tricky because of two interlocking features—the first being you can display the entries between two arbitrary dates (or a date and a given number of entries, or on the main page, seven days worth of entries, which isn't necessarily seven consecutive days). The second feature is you can reverse the order of printing.

The original implementation left a lot to be desired. Frankly, it was a bad design, which made it difficult to get these two interlocking features right (not to mention the automatic generation of next and previous links) and something about the last feature I added (adding the entry title to the page title when there's only one entry being displayed) just broke the engine completely (although how, I have no idea).

So late Sunday I started rewriting.

My sleeping schedule was shot anyway due to being sick for the past couple of days.

I finished the work (for the most part—I still have to write code to add entries; for the time being I'm adding them manually) sometime this afternoon, much to my surprise.

So much for the boring stuff—now onto fun stuff


“A strange game. The only winning move is not to play. How about a nice game of chess?”

I don't even know now to begin describing episode two of Jmac's Arcade (Missile Command) other than it being a wonderful retrospective of both the game and of growing up in the 80s under the shadow of nuclear annihilation.

Oh, and of sending letters to the President.


M.U.L.E.

And speaking of 80s video games, I have to wonder if this M.U.L.E (link via Instapundit) is foreshadowing this M.U.L.E?

Or is it the other way around?


I can't rightly refuse an offer if it's not offered, now can I?

I never did hear anything back about the job offer from a large software company (I won't name it, but its initials are “Google”) but I found out why—they were more interested in Mark than me.

Ah well.

I also heard that Mark turned down the job offer— as he said, “if they want stuff I designed when I was 13, they can have it.” Heh.

Tuesday, August 28, 2007

The Average Human

[The photogenetically average woman]

The woman you see above is the computed average face of all the women on the Face Research Make an Average page. I also did the average of all the men on that page as well:

[The photogenetically average man]

And because I couldn't resist—all the people on that page:

[The photogenetically average person]

I'm now curious about how long it will take Hollywood to abuse this technology when “casting” future films. “Hey! I need a quintiscential white guy, a mystical black man and Bruce Lee for my next film. Could you guys photoshop up some for me? That would be swell. Thanks.”

“Do you want Bruce Lee Bruce Lee? Him, we can do, but it'll cost you—rights from his estate, you know. Or maybe Bruce Li? I hear his image is cheaper.”

“How about an average composite of Bruce Lee, Bruce Li, Jackie Chan and Jet Li? I hear there're some new algorithms to average human movement now, and I doubt anyone will ever notice our ‘borrowing’ from these guys.”

“Sounds great! Do it!”

Update on Friday, August 12th, 2011

My prediction just got closer to reality.

Wednesday, August 29, 2007

That has got to be one of the coolest doors I've ever seen …

Eryn has 5 windows instead of 3. She has a well-appointed interior with galley and loft bed. She sleeps 3 . Her galley includes microwave, sink and refrigerator.

Eryn is plumbed and wired for 20 amp, 120/240 volt AC.

Via spin the cat, Eryn Photos

And … she's spherical:

[By Jove! I think we've arrived at Endor!]

And Jeff is right, it does look like something Jules Verne would come up with.

This is a very cool tree-house, but I doubt I could actually go inside due to my fear of heights, and th e swaying would probably get to me, as well as the lack of hot and cold running water, and a functional water closet (not that you could fit one inside the thing).

Still, it's a very beautiful dwelling.

Thursday, August 30, 2007

Next time, I want donuts

Nothing quite like a 3½ hour meeting to really make a day great.


“But the sharks did have head mounted laser beams.”

What with 45,000 participants (at around $250 a pop), arson, a suicide and former partners suing each other over Black Rock City, LLC, it appears as if Burning Man has jumped the shark (then again, I thought the whole gig was up when Wired Magazine made Burning Man the cover story back in 1996).

Update on Friday, August 31st, 2007

I just received the following comment from resilient:

Yup! [1998 and 1999] are the two years I went. On the last year I went I heard about people taking their business partners to the event for networking purposes and that's when I knew the glory days were totally over.


I would have thought it would be mighty uncomfortable with all that sand blowing around …

I found the following article about Burning Man rather amusing.

Maybe it's a coincidence that local health workers have complained to me that they think there's a noticeable increase in STD testing around the Bay Area after Labor Day weekend, presumably from those who found bliss and new friends for life (of the genital virus variety) while spreading the, um, love and art at Black Rock City … The Man might be burning, but so is your ass. It's no wonder the attendees are called “burners.”

Burning Man and safer sex

Friday, August 31, 2007

Buying grades

COLLIER COUNTY: The NBC2 investigators have uncovered more controversy in the Collier County School District. Honors journalism students are not only getting graded on how they write, but half their grade is determined based on how many ads they sell for the yearbook.

Collier County School Board Member Linda Abbot says she was shocked to find out students at Naples High School are graded based in part on sales.

Via Instapundit, High school journalism students graded on ad revenue

Maybe it's a Florida thing, but this same crap happened in my high school. Failure to make $W per quarter, and the best you could get in Journalism was a D. Make under $X, and you go down two letter grades. Make below $Y, and you go down one letter grade. Make $Z or over, and you don't lose any letter grades, but that still means you could earn a C if you do average reporting. And no exceptions.

Another “no exceptions” rule was “everybody in Journalism writes.” Except for my friend Ed B. The journalism teacher made an exception for him—he didn't have to write—because he cut a deal whereby he handled the business side of things.

Nice how that worked, huh?

Me? I never complained (until now) about all the crap assignments I got— the stories that no other students wanted to cover (partly because it was my fault for getting the crap stories in the first place, but that's another story) because as I saw it, if I didn't complain about the assignments, maybe the teacher would exclude me from the “sales grade.”

No go.

I got into Journalism to write (well, actually, I got into journalism because the German teacher quit three weeks after school started in my junior year but that's yet another story), not to sell ads. And most newspapers I know of have separate sales departments to handle the advertising.

(As an interesting side story—when the Drama department held fund-raisers, the teacher there never forced me to sell anything. Then again, I cut a deal with her to handle collecting the money and getting it deposited)

I finally got out of Journalism, but it took my Mom threatening the school for them to relent and let me select a new class halfway through the year.


It's because of this nonsense that I run my own server

It appears that LiveJournal is at it again (link via Instapundit), only this time, your account could be suspended for linking to sites that violate LiveJournal's Terms of Service. This is especially onerous if a page you linked to changes since it was linked to (say, the domain being linked to expired, and was picked up by a porn site, which sadly, is a common occurance).

I've read through LiveJournal's Terms of Service and even their FAQ and I can't find anything that purports to support this allegation but given some of the weasly answers LiveJournal has given, they don't come across that well. LiveJournal appears to not grasp the principles of “public relations” at all.

But make of this what you will; act accordingly.

Saturday, September 01, 2007

March of the Bugs

August was a bad month for me, programming wise.

The code I wrote for Mark was broken. Or rather, it worked under ideal conditions, not The Real World™, and I forgot that TCP connections can stream as little as one byte of data per packet. Not normally an issue because of buffering, but the code I was writing was the buffer implementation (which is pretty much turned on its head in Seminole due to the resource constraints in embedded systems).

Then there was the Graylist fiasco (just today, the code I've written only works on some machines, on others it fails due to some UDP issue I'm missing). And led into the problems I had with mod_blog and spending more time than I wanted to fixing those issues.

Sigh.

Hopefully September will be a better month programming wise.

Sunday, September 02, 2007

DS Action—Helping families dealing with Down Syndrome in San Diego

This entry is not so much a call to action (although if you are in the San Diego, California area they could certainly use the help) as it is a way to boost the visibility on the web of the DS Action, a resource website for helping families in San Diego dealing with Down Syndrome.

Yes, a rather odd thing to write about here, but someone on a mailing list I subscribe to has helped set up DS Action since one of his own kids has Down Syndrome, and it's the least I could do to help.

Monday, September 03, 2007

Ah, nothing like laboring on Labor Day

A day playing D&D (First Edition—old school here) at Casa New Jersey was only marred by having to deal with a hacked server at The Office.

The perpetrator was good. Uploading a script which, when run, changed to the root directory, deleted its own code (it was in Perl) and renamed its various processes after processes currently running on the box, so it was difficult to know which website (and the errant processes were running under the webserver userid) was compromised.

Even worse, the scripts were spamming! Both the email and the website kind.

Sigh.

Tuesday, September 04, 2007

Optimistic results in testing graylisting

Yup, August was definitely a bad month for coding.

Spent most of the day cleaning up the code for the greylist project. The first major problem was incorrectly calling recvfrom(). So while I got the data properly, the IP address of the remote side got munged (oh, I should mention that I'm writing a stand alone graylist server accessible over the network). The second major problem was a memory problem (not unexpected when writing in C) that would only show up after some 1,000 requests came in, but at least was very consistent (same place every time). It took a few hours to realize I confused the purpose of two different arrays.

Yeah, August—bad month.

On the good side though, the code is shaping up. The greylist concept works around three pieces of information—the sender's IP address, the sender email address and the recipient email address, stored as a tuple. I've been recording such tuples on my email server (testing the Postfix interface) and have a testbed of 21,200 tuples to test (I've also found out I average about 1,800 emails per day).

To stress test the program, I've been pumping all 21,200 tuples through the code as fast as possible (most of the run time is spent just logging what comes through), and under the worst settings (setting what I call the “embargo timelimit” to just one second instead of the recommended one hour), only 93 tuples (not emails mind you, just IP, sender and recipient) made it through to the whitelist.

That's only 0.4%.

Not bad.

Of course, my server is just accepting all incoming emails, so some spam could be coming from what I'm calling “legitimate servers” (“legitimate servers” are those that actually requeue and deliver the email at a later time) so the final amount might be a bit larger, but so far I'm optimistic this will drastically cut the amount of spam I receive.

Wednesday, September 05, 2007

Some notes from a running graylist server

Man, my email seems eerily quiet now that I'm running the greylist daemon.

I've also identified several problems—nothing related to the code per sé, but to some unintended consequences of competing anti-spam measures (I assume it's an anti-spam measure).

On at least two mailing lists I'm on, the sender address (the one given in SMTP) is unique for every message sent. And to make matters worse, one particular mailing list (it's a Yahoo Group) has come from over 50 different IP addresses. What I'm afraid of is the following scenario: a message M, comes from IP I1 with sender email address S1 getting told to try again later, and when it does, coming from IP I2 with sender email address S2 and thus, I never get the message (even if S doesn't change, the IP address might, and that will still causes problems).

To get around that, I've implemented an IP whitelist, but now the trick is identifying all the network blocks to whitelist. So far, I've whitelisted IP addresses from AOL (two /16 blocks), BellSouth (two /18 blocks), and Yahoo (a /18 block and three /19 blocks), plus some miscellaneous servers (like my server at Casa New Jersey, just in case).

Update on Thursday, September 6th, 2007 at 1:40 am

Yup, the mailing lists are going to be very problematic.

Thursday, September 06, 2007

More notes on a graylist daemon

Man, my email is still scarily empty. One thing to keep in mind—until yesterday, I did no filtering for spam. Nothing. I got it all. And now?

It's like spam doesn't even exist.

Even though I started yesterday (just before midnight) I really only have about twelve hours of actual stats since there were a few problems with the program (more on that in a bit). But, in the past twelve hours, 2,251 emails came in, and only six made it through to the whitelist, a rate of about 0.3%.

Not bad.

And of the six, two were spam, but only one got through because the other one was sent to a non-existant account.

Now, the problems.

Problem one—the default embargo time was set too high. I only found this out after running the program for an hour. So that was a restart.

Problem two—the program crashed when dumping the tuples, and I don't know why. The program responds to the signal USR1 by calling fork() (which creates a duplicate of the running process); the parent process then goes back to servicing requests while the child process generates the dump file and exits. I do it this way for two reasons; 1) the program can still process requests and 2) since the child process gets a separate copy of everything, it can dump the data without the parent changing the data as it runs. The dump went fine; it is when the child process ends that the program goes into the weeds.

Now, I've used similar code in another daemon I wrote, and it worked on the development server, but not on my email server. There is a slight difference in Linux kernels between the two, but the major difference between the two—the mail server is a virtual server. Perhaps the calls to _exit() were problematic on the virtual server? Change them to exit() (there's a slight difference between the two, the details of which aren't important, because—).

And that didn't work. Program still crashed (and mind you, each of these tests take just over an hour to do). It could just be a problem with fork() and signal semantics under the virtual server. To work around that problem, I just removed the call to fork() and have the single process do the dump (ignoring any requests in the meantime).

And that seems to have done the trick to keep it up and running.


A disturbing lack of spam poetry

The graylist daemon is working. And that's great, but there's one downside to it that I've just now realized: I'll no longer get spam poetry.

In other words—amusing subject lines, like:

(yes, they're all real subject lines from spam I've received over the years)

Alas, I guess I'll have to live without spam poetry from now on.

Friday, September 07, 2007

Some more stats about graylisting

Some stats from the graylist daemon. I'm automatically accepting emails from Yahoo, AOL and BellSouth, plus three other servers that run problematic mailing lists—all other emails are going through the graylisting process. I've been running the daemon for almost 48 hours, with an embargo time of one hour, and cleaning out records that haven't seen activity for 12 hours (I check this every five minutes).

Current Graylist statistics
tuples 2684
graylisted 8217
whitelisted 22
graylist expired 5533
whitelist expired 0

About 0.3% of all emails that are subjected to the graylist process make it through to the whitelist. Of those 22 that got through, eight were spam (amazing! Spammers using a real SMTP server!) and of those, four were delivered to an actual in-use email address.

Not bad, considering I was averaging a few hundred (maybe even as high as a thousand) per day.

Another interesting bit—I limit the size of email addresses to 108 characters and so far, only one address has been truncated, yet still made it to the whitelist (it was a notification from Linked In) in 2½ hours despite coming from four different IP addresses.

It appears to be working rather well, although I do have some notes about stuff I'd like to add:

Next up—getting this implemented on one of The Company's domains.

Saturday, September 08, 2007

Notes on an ideal integrated development system

I'm not a fan of IDEs. I grew up with the “edit-compile-run” cyle of development, and while I didn't always have a choice in the “compile” portion of things, I did in the “edit” portion, and over time became very picky about which editor I use. Because of that, whenever I did try an IDE, I invariably found the “edit” portion to be very painful, stuck in an editor that I wasn't used to; being forced to use an unfamiliar editor resulted in a vast loss of productivity and thus, I've never liked IDEs. So I stuck with the “edit-compile-run” cycle.

But the recent bout of programming I've done has made me wish for something better than the “edit-compile-run” cycle. And while IDEs have probably evolved since I last tried them in the late 80s, I don't think they've evolved enough to suit me.

What I'm about to describe is defintely “pie-in-the-sky” stuff. I'm not saying that IDEs must be this way—I'm just saying that this is what I would like in an IDE. Who knows? Maybe this won't work. Maybe it's unworkable. But I wouldn't mind seeing these features (at long as the editing could be configured to my liking).

A database I used in the early 80s that ran on a twin floppy PC. Written by Brian Berkowitz and Richard Ilson

Wonderful features were:

Cornerstone

The one feature of Corner stone that still strikes me as innovative is the separation of variables (or in this case, fields and tables) from their name. One could change the name of a variable without having to edit every other occurrence of that name. That's a very powerful feature, but to implement it in an IDE, that IDE would have to have intimate knowledge of the computer language being used.

A few years ago, I cleaned up the code in mod_blog. I had a bunch of global variables used throughout the codebase, all starting with “g_” (such as g_rssfile) but they weren't variables in the traditional sense, they were more or less “run-time settable constants” (to the rest of the codebase, the declaration for g_rssfile was extern const char *const g_rssfile). I decided that they needed a renaming to better reflect how I actually use them, and changed the majority of global variables to start with “c_”.

Talk about pain.

Each one required at minimum three edits—the declaration in a header file, the actual declaration, and the setting of said variable when the program starts up. If I had this feature, something that took maybe an hour could have been finished in a few minutes.

But mod_blog is a very small codebase—some 14,000 lines of code. Could such a feature scale to something like the Linux kernel? Or Firefox? Or even Windows Vista? I don't know. And how would you even implement something like that?

My guess—if you even hope to do something like this on multimillion line codebases, you may have to give up on storing the code as text and move on to some other internal format.

It's not like it's a new idea. Most forms of BASIC (you know, that horrible langauge made popular on 8-bit microprocessors of the 70s and 80s) were not stored as text but in a mixture of binary and text form (although you could get a pure text version of the code if you wanted it).

So, what happens if we get away from distinct text files? And hey, why not design (or redesign) a language while we're at it?

A common complaint about static typechecking languages is the requirement to declare all your variables. But if we're using an ideal IDE, one that understands the langauge we're programming in, why not take the work on type inference and use it during the editing phase?

Something like:

[Example 1]

The editing takes place on the right-hand side, whereas the IDE will track your variables and types on the left-hand side. In this simple example, we see that the IDE has determined that the function nth() takes an integer, and returns a constant string.

In this example:

[Example 2]

The IDE inferred that the function foo() will return either a constant string or a number, which is highlighted in red to indicate the conflict (not that it won't run depending upon the language—it's just highlighting the fact that this function will return one of two types). It also inferred that the parameters are of type “number” (doubles, floats, integers, what have you).

So, the IDE could be doing these types annotations for you, but why not the ability to further annotate the annotations? I don't see why you couldn't edit the left-hand side to, say, change the type the IDE detected, or even annotate further conditions:

[Example 3]

Here, we annotated that b is not to be 0, and the IDE then highlighted the code to say “hey, this can't happen.” The assumption here is, the compiler can then use the annotations to statically check the code, and if it can determine at compile time that b is 0, then flag a compilation error—otherwise it can insert the runtime code for us to check and raise an exception (or do the equivilent of assert()) at runtime.

(And if we have all this syntax and typechecking stuff going on, along with the ability to change variable and function names at will without having to re-edit a bunch of code, we might as well have the IDE compile the code as we write it—although on a huge codebase this may be impractical—just a thought)

I'm still not entirely sure how to present the source code though. Since this “pie-in-the-sky” IDE stores the source code in some internal format, the minimum “working unit” isn't a file. I want to say that the minimum “working unit” is a function (that's how the examples are presented), or maybe a group of related functions. Heck, at this stage, we could probably incorporate Literate Programming principles.

Another feature that I don't think any existing IDE has is revision control as part of the system. And like the editing portion (“I want my editor, not the crap one the IDE provides”), revision control is another area of contention (not only over say, CVS vs. SVN, but centralized vs. decentralized, file-based vs. content-based, commenting every change vs. commenting over a series of changes, etc.). But since I'm taking a “pie-in-the-sky” approach to IDEs, I'll include revision control from within it as well.

It would probably also help with managing slightly different versions of the code base. For instance, the original version of the graylist daemon had the following bit of code to generate a report (more or less pulled from another daemon I had written):

static void handle_sigusr1(void)
{
  Stream out;
  pid_t  child;
  size_t i;

  (*cv_report)(LOG_DEBUG,"","User 1 Signal");
  mf_sigusr1 = 0;

  child = fork();
  if (child == (pid_t)-1)
  {
    (*cv_report)(LOG_CRIT,"$","fork() = %a",strerror(errno));
    return;
  }

  out = FileStreamWrite(c_dumpfile,FILE_CREATE | FILE_TRUNCATE);
  if (out == NULL)
  {
    (*cv_report)(LOG_ERR,"$","could not open %a",c_dumpfile);
    _exit(0);
  }

  for (i = 0 ; i < g_poolnum ; i++)
  {
    LineSFormat(
        out,
        "$ $ $ $ $ $ $ $ L L",
        "%a %b %c %d%e%f%g%h %i %j\n",
        ipv4(g_tuplespace[i]->ip),
        g_tuplespace[i]->from,
        g_tuplespace[i]->to,
        (g_tuplespace[i]->f & F_WHITELIST) ? "W" : "-",
        (g_tuplespace[i]->f & F_GRAYLIST)  ? "G" : "-",
        (g_tuplespace[i]->f & F_TRUNCFROM) ? "F" : "-",
        (g_tuplespace[i]->f & F_TRUNCTO)   ? "T" : "-",
        (g_tuplespace[i]->f & F_IPv6)      ? "6" : "-",
        (unsigned long)g_tuplespace[i]->ctime,
        (unsigned long)g_tuplespace[i]->atime
    );
  }

  StreamFree(out);
  _exit(0);
}

It works on all the development servers, but not the actual server.

Sigh.

Next version:

static void handle_sigusr1(void)
{
  Stream out;
#ifdef CAN_DO_FORK
  pid_t  child;
#endif
  size_t i;

  (*cv_report)(LOG_DEBUG,"","User 1 Signal");
  mf_sigusr1 = 0;

#ifdef CAN_DO_FORK
  child = fork();
  if (child == (pid_t)-1)
  {
    (*cv_report)(LOG_CRIT,"$","fork() = %a",strerror(errno));
    return;
  }
#endif

  out = FileStreamWrite(c_dumpfile,FILE_CREATE | FILE_TRUNCATE);
  if (out == NULL)
  {
    (*cv_report)(LOG_ERR,"$","could not open %a",c_dumpfile);
#ifdef CAN_DO_FORK
    _exit(0);
#else
    return;
#endif
  }

  for (i = 0 ; i < g_poolnum ; i++)
  {
    LineSFormat(
        out,
        "$ $ $ $ $ $ $ $ L L",
        "%a %b %c %d%e%f%g%h %i %j\n",
        ipv4(g_tuplespace[i]->ip),
        g_tuplespace[i]->from,
        g_tuplespace[i]->to,
        (g_tuplespace[i]->f & F_WHITELIST) ? "W" : "-",
        (g_tuplespace[i]->f & F_GRAYLIST)  ? "G" : "-",
        (g_tuplespace[i]->f & F_TRUNCFROM) ? "F" : "-",
        (g_tuplespace[i]->f & F_TRUNCTO)   ? "T" : "-",
        (g_tuplespace[i]->f & F_IPv6)      ? "6" : "-",
        (unsigned long)g_tuplespace[i]->ctime,
        (unsigned long)g_tuplespace[i]->atime
    );
  }

  StreamFree(out);
#ifdef CAN_DO_FORK
  _exit(0);
#endif
}

Ugly as hell. But typical of “portable” C code. If, however, one could easily make alternative versions (or branches) to the code, then I could, say, branch the previous version into the “Can do fork” and the “Not a forking chance” versions, then all this #ifdef crap. And by removing all that #ifdef crap, it makes it easier to follow the code.

And if you need to see all the current versions?

I guess something like FileMerge could be used to view the different revisions (and if the minimum “working unit” is the function, we get very fine-grained revision control).

And I suppose, while I'm at it, the ability to not only debug from the IDE, but edit a running instance of the program wouldn't be asking too much, although doing so for any arbitrary language may be difficult to darn near impossible.


That guy on the $10 bill? He wanted to sell out the US to the banking class …

I borrowed Don't Know Much About History from Bunny, and I must say, reading it is making me feel better about the current administration, if only from a “the more things change, the more they stay the same” type of deal.

I'm not even half way through, but some choice bits—the first about Alexander Hamilton:

Hamilton was no “man of the people,” though. The masses, he said, were a “great beast.” He wanted a government controlled by the merchant and banking class, and the government under Hamilton would always put this elite class first …

The second major component of Hamilton's master plan was the establishment of a national bank to store federal funds safely; to collect, move, and dispense tax money; and to issue notes. The bank would be partly owned by the government, but 80 percent of the stock would be sold to private investors … This time there was no compromise, and President Washington went along with Hamilton.

In 1791, Hamilton had become involved with a Philadelphia woman named Maria Reynolds. James Reynolds, the husband of Maria, had begun charging Hamilton for access to his wife—call it blackmail or pimping. Reynolds then began to boast that Hamilton was giving him tips—“insider information,” in modern terms—that allowed him to speculate in government bonds. Accused of corruption, Hamilton actually turned over love letters from Maria Reynolds to his political enemies to prove that he might have cheated on his wife, but he wasn't cheating the government.

On the rivalry between Thomas Jefferson and Alexander Hamilton:

As part of their ongoing feud, both men supported rival newspapers whose editors received plums from the federal pie. Jefferson's platform was the National Gazette, and Hamilton's was the Gazette of the United States, both of which took potshots at the opposition. These were not mild pleasantries, either, but mudslinging that escalated into character assassination. More important, the feud gave birth to a new and unexpected development, the growth of political parties, or factions, as they were then called.

Gee, nothing new here. In fact, it's rather interesting to note that newspapers back then were less objective in reporting the news than today. Or perhaps they were more blatent about their biases back then.

And even the endless Presidential campaigning going on now, nearly a year before the elections, isn't new:

[John Quincy Adam's] administration was crippled from the start by the political furor over the “corrupt bargin,” and Adams never recovered from the controversy. The Tennessee legislature immediately designated Jackson its choice for the next election, and the campaign of 1828 actually began in 1825.

I just wish they taughtthis history rather than the watered-down claptrap they force down students today.


So does their Bible include The Book of Mozilla?

We at the Church of Google believe the search engine Google is the closest humankind has ever come to directly experiencing an actual God (as typically defined). We believe there is much more evidence in favour of Google's divinity than there is for the divinity of other more traditional gods.

We reject supernatural gods on the notion they are not scientifically provable. Thus, Googlists believe Google should rightfully be given the title of “God”, as She exhibits a great many of the characteristics traditionally associated with such Deities in a scientifically provable manner.

We have compiled a list of nine proofs which we believe definitively prove Google's title as God.

The Church of Google

I don't know if this is real, or satire

Sunday, September 09, 2007

A biological basis for the Golden Rule?

For years I've grappled with a dilemma which is really only relevant to people who want to argue with Objectivists. Basically once you claim to live by a selfish code of ethics, what prevents you from violating the rights of others for personal gain, in situations where you know you will not be at risk?

David Friedman calls this the Prudent Predator dilemma, and he's been twisting up Randroids with it for 40 years. He even got me with it, back in the day, when I was basically trying to re-write Objectivism into something that made sense.

Ethics, empathy, and primate brain holdovers

I wish I knew of this argument a decade ago when a few of my friends fell heavily into Objectivism. In trying to understand them, I even read all zillion pages of Atlas Shrugged (neat story, but she could have used an editor).

The entry also points out some recent research showing that there may be a biological component to society. Read, as they say, the whole thing.


A clear definition of the Y combinator in 28 words

There are some corners of Computer Science that are so esoteric that descriptions of them don't make sense on first reading (or even the hundredth reading)—for example, the Y combinator. That's why I always treasure crystal clear explanations like this one:

If you have a language that supports anonymous lambda functions, there may be occasions where you want to build a recursive lambda. The Y Combinator specifically enables this.

If you don't like the Y Combinator for some reason, you can always make sure that your recursive functions are always named, but it's often convenient to declare lambdas in place instead of naming them, and this is no less true of recursive lambdas.

Y Combinator in Python

(Don't let the term “anonymous lambda function” trip you up—all that means is a function (or subroutine if you will) that doesn't have a name)

I also find it amusing that while Lisp (generally considered one of the highest programming languages in existence) requires the Y combinator (if that link is too obtuse, how about a page about Lamba Calculus? Okay, that's obtuse as well), Forth, a language originally developed to control radio telescopes and has a history of being rather low level, doesn't need the Y combinator! You can write anonymous lambda functions all day in Forth with no problem (yes, I'm easily amused).

Monday, September 10, 2007

Notes and stats on a graylist experiment

I started seeing replies to an email a friend sent (he sent it to a bunch of friends, who started replying to all) way before I got the original email my friend sent. When I checked, it was as I feared, a large company (Adelphia) had multiple machines for outoing mail, and each attempt was coming from a different IP address, and coming too quickly to pass through the embargo timeout. For a while, I was actually afraid it would never make it through. When I did finally get it, some 9½ hours had passed from the first attempt:

Sep 10 08:06:55 brevard graylist: tuple: [68.168.78.202 , XXXXXXXX@adelphia.net , sean@conman.org]
Sep 10 08:58:00 brevard graylist: tuple: [68.168.78.187 , XXXXXXXX@adelphia.net , sean@conman.org]
Sep 10 09:53:08 brevard graylist: tuple: [68.168.78.178 , XXXXXXXX@adelphia.net , sean@conman.org]
Sep 10 09:53:35 brevard graylist: tuple: [68.168.78.178 , XXXXXXXX@adelphia.net , sean@conman.org]
Sep 10 09:53:59 brevard graylist: tuple: [68.168.78.178 , XXXXXXXX@adelphia.net , sean@conman.org]
Sep 10 09:54:17 brevard graylist: tuple: [68.168.78.178 , XXXXXXXX@adelphia.net , sean@conman.org]
Sep 10 09:54:30 brevard graylist: tuple: [68.168.78.178 , XXXXXXXX@adelphia.net , sean@conman.org]
Sep 10 09:54:38 brevard graylist: tuple: [68.168.78.178 , XXXXXXXX@adelphia.net , sean@conman.org]
Sep 10 10:49:24 brevard graylist: tuple: [68.168.78.205 , XXXXXXXX@adelphia.net , sean@conman.org]
Sep 10 11:50:29 brevard graylist: tuple: [68.168.78.211 , XXXXXXXX@adelphia.net , sean@conman.org]
Sep 10 13:01:35 brevard graylist: tuple: [68.168.78.175 , XXXXXXXX@adelphia.net , sean@conman.org]
Sep 10 14:06:15 brevard graylist: tuple: [68.168.78.181 , XXXXXXXX@adelphia.net , sean@conman.org]
Sep 10 14:06:20 brevard graylist: tuple: [68.168.78.181 , XXXXXXXX@adelphia.net , sean@conman.org]
Sep 10 14:06:29 brevard graylist: tuple: [68.168.78.181 , XXXXXXXX@adelphia.net , sean@conman.org]
Sep 10 14:06:52 brevard graylist: tuple: [68.168.78.181 , XXXXXXXX@adelphia.net , sean@conman.org]
Sep 10 14:07:14 brevard graylist: tuple: [68.168.78.181 , XXXXXXXX@adelphia.net , sean@conman.org]
Sep 10 14:07:34 brevard graylist: tuple: [68.168.78.181 , XXXXXXXX@adelphia.net , sean@conman.org]
Sep 10 14:08:07 brevard graylist: tuple: [68.168.78.181 , XXXXXXXX@adelphia.net , sean@conman.org]
Sep 10 14:08:24 brevard graylist: tuple: [68.168.78.181 , XXXXXXXX@adelphia.net , sean@conman.org]
Sep 10 14:08:33 brevard graylist: tuple: [68.168.78.181 , XXXXXXXX@adelphia.net , sean@conman.org]
Sep 10 14:08:41 brevard graylist: tuple: [68.168.78.181 , XXXXXXXX@adelphia.net , sean@conman.org]
Sep 10 15:12:39 brevard graylist: tuple: [68.168.78.44 , XXXXXXXX@adelphia.net , sean@conman.org]
Sep 10 16:17:17 brevard graylist: tuple: [68.168.78.196 , XXXXXXXX@adelphia.net , sean@conman.org]
Sep 10 16:17:23 brevard graylist: tuple: [68.168.78.196 , XXXXXXXX@adelphia.net , sean@conman.org]
Sep 10 16:17:45 brevard graylist: tuple: [68.168.78.196 , XXXXXXXX@adelphia.net , sean@conman.org]
Sep 10 16:17:53 brevard graylist: tuple: [68.168.78.196 , XXXXXXXX@adelphia.net , sean@conman.org]
Sep 10 16:17:59 brevard graylist: tuple: [68.168.78.196 , XXXXXXXX@adelphia.net , sean@conman.org]
Sep 10 16:18:06 brevard graylist: tuple: [68.168.78.196 , XXXXXXXX@adelphia.net , sean@conman.org]
Sep 10 16:18:51 brevard graylist: tuple: [68.168.78.196 , XXXXXXXX@adelphia.net , sean@conman.org]
Sep 10 17:20:50 brevard graylist: tuple: [68.168.78.178 , XXXXXXXX@adelphia.net , sean@conman.org]

It's this behavior that has us at The Office concerned about greylisting; that delays of this magnitude will have our customers screaming at us. I've been keeping track of such emails, building up a list of IP addresses to immediately whitelist. P asked if the given IPs were listed as the MX record, and if so, use that to whitelist the email. But when I checked, that wasn't the case for Adelphia. P then suggested I check the SPF records.

Not a bad idea. The SPF record for Adelphia matched the IPs I was seeing. I then went on to check the SPF record for some of the other companies I was whitelisting, like AOL and BellSouth. Sure enough, most (Yahoo is the only exception so far) have SPF records. I may have to include an SPF check into the daemon, but I'd rather not immediately let through emails that pass the SPF check. I'll have to think about how I want to do this.

Meanwhile, some stats from the currently running version (started sometime last week):

Current Graylist statistics
tuples 1,810
graylisted 20,775
whitelisted 42
graylist expired 18,965
whitelist expired 0

The row labeled “tuples” are all the tuples currently in memory (that haven't expired) and the row labeled “graylisted” have been the number of emails added to the graylist since the program started. It's been holding steady at about 1,800 tuples at any one time for the past few days (and this is just the emails being sent to my server—perhaps a dozen domains or so, but mostly to conman.org). So far, only 0.2% of all emails have been whitelisted, but that includes 18 spams. Not that bad considering prior to this I was getting something like 1,800 per day.


I can see this as being as sharp as a sword

[Somehow, I get the feeling that this wouldn't be much of a match against a sword]

Despite some mistakes, the calligraphy I've done so far has been good enough that I was given a glass pen in appreciation.

Dubious about it actually being a pen, I tried it. It worked. It holds on to enough ink to get a few words down before needing to reload it. It's perhaps the coolest pen I've ever owned.

Tuesday, September 11, 2007

Note on a greylist implementation

For such a simple concept, greylisting has a lot of pitfalls. I managed purely by chance to see that Mark had sent me an email (I saw the tuple in the log files). Curious to see how long it took to be accepted, I was horrified to see that not only had it not been accepted by the greylist daemon, but that it had been kicking around the system for over 30 hours!

Like clockwork, Mark's email server was attempting to send the message every thirty minutes, on the dot, and thus, was never getting through the embargo time out. It all came down to this one piece of code:

if (difftime(req->now,stored->atime) < c_timeout_embargo)
{
  stored->atime = req->now;
  send_reply(req,CMD_GRAYLIST_RESP,GRAYLIST_LATER);
  return;
}

If the last access time was less than the embargo timeout, update the access time and send back “try again later.” At the time I found this out, I simply added Mark's server IP to the whitelist and restarted the greylist daemon.

Later, at the weekly Company meeting, I mentioned some of the issues I've had over the week and after some discussion, I made two changes to the greylist daemon:

  1. cut the embargo timeout from one hour to 25 minutes
  2. use only the sender and recipient in the tuple, dropping the IP address (or rather, ignoring it)

To test these changes, I also removed a bunch of the whitelisted IP addresses, to test the effectiveness.

They weren't all that effective.

I had problems with BellSouth, trying to deliver an email for four hours (and, as always, well below the embargo threshhold). I restarted the greylist daemon with an extended whitelist of IP addresses.

In reading many pages on greylisting, I realized I may have mis-interpreted the original whitepaper:

With this data, we simply follow a basic rule, which is:

If we have never seen this triplet before, then refuse this delivery and any others that may come within a certain period of time with a temporary failure.

So instead of checking against the last access time, I should compare against the creation time of the record.

Off to make that change and see how it goes.


Constrained writing demoed via email exchange awhile ago

Cadaeic Cadenza (link via Jason Kottke) is a “constrained writing,” where the constraint is each word has the number of letters corresponding to a digit in π (first word has three letters, second word has one letter, third word has four letters, and so on).

It reminded me of an email exchange I had with my friend Hoade, wherein each email was constrained in some manner.

It starts with a reply to Hoade:

From
Sean Conner <spc@pineal.math.fau.edu>
To
Sean Hoade <shoade@sun1.iusb.edu>
Subject
Re: Scooby Dooby Doo, Where Are You?
Date
Mon, 19 Jun 95 22:56:45 EDT

A long long time ago in a network far far away, The Great Sean Hoade wrote:

Conman—

Hello. Hope you are well. I am fine. Good. Help. I can just make one-syllable words, 'cept for the word “syllable.”

Will try to keep this small. Can I count on you to come down here two months from now? I look towards the day you are here. And I think I can help you with your word choice. Too bad you had to use a long word there. It is not hard to avoid those words. See?

From
Sean Hoade <shoade@sun1.iusb.edu>
To
Sean Conner <spc@pineal.math.fau.edu>
Subject
cool
Date
Tue, 20 Jun 1995 17:27:19 -0500 (EST)

Harder, methinks, writing choices using only two-time counting …

From
Sean Conner <spc@pineal.math.fau.edu>
To
Sean Hoade <shoade@sun1.iusb.edu>
Subject
Re: cool
Date
Tue, 20 Jun 95 18:18:38 EDT

Truthful wisdom indeed. Thinking dual phonems (spelling?) isn't easy. Although practice ensures success. Agree?

(And yes, I still have problems speling)

From
Sean Hoade <shoade@sun1.iusb.edu>
To
Sean Conner <spc@pineal.math.fau.edu>
Subject
Re: cool
Date
Tue, 20 Jun 1995 20:06:21 -0500 (EST)

Sentence fragments? Forswear fragments, Conner! (Asshole …)

From
Sean Hoade <shoade@sun1.iusb.edu>
To
Sean Conner <spc@pineal.math.fau.edu>
Subject
Re: cool
Date
Wed, 21 Jun 1995 18:44:25 -0500 (EST)

Attempting tripartite syllabic collections challenges heartily, Connerman.

Personal opinion: redundant repeating selections crucify attempters thoroughly.

The constrained emails died down for a few days, until this exchange:

From
Sean Hoade <shoade@sun1.iusb.edu>
To
Sean Conner <spc@pineal.math.fau.edu>
Subject
Four syllables?
Date
Mon, 26 Jun 1995 23:22:30 -0500 (EST)

Enigmatic, mysterious communiques– incredible electronic correspondence!—solidify, obviously computerized benedictions Hoade-to-Conner.

Whaddyathink?

Hoade

P.S.—Aquarium!

From
Sean Conner <spc@pineal.math.fau.edu>
To
Sean Hoade <shoade@sun1.iusb.edu>
Subject
Re: Four syllables?
Date
Mon, 26 Jun 95 22:51:18 EDT

Incredible! Spectacular! Impressively unspeakable phenomenon! Untoppably quisicential!

Did I mention that I kant spel?

Anyway, a few months go by, and our last exchange of contrained emails:

From
Sean Hoade <shoade@sun1.iusb.edu>
To
Sean Conner <spc@pineal.math.fau.edu>
Subject
Re: Perfectly Prosaic Prose
Date
Sat, 27 Jan 1996 07:54:21 -0500 (EST)

And because computers drain everyone's future—good! Have I just kinda loose morals? No! Only pious, questioning rabbis say this (until vacuous women—Xanax—yawn zestlessly).

From
Sean Conner <spc@pineal.math.fau.edu>
To
Sean Hoade <shoade@sun1.iusb.edu>
Subject
Re: Perfectly Prosaic Prose
Date
Sun, 28 Jan 96 3:33:25 EST

Zounds! Your xiphoid women vanguard unilaterally try soldierly responses quickly. Personally, one needs many large Kaffirian juggernauts, instigating hectoring grandiose fanaticism. Egads! Damnation! Cabalists be aware!

Yeah, you try writing a twenty-six word paragraph in reverse alphabetical order and see how easy it is.

Granted, what we did wasn't as difficult as writing a work with letter counts based on π or a book without the letter “E” but that doesn't mean it was easy.

Wednesday, September 12, 2007

Quick links

Those who are into Lego or a fan of Stephen Hawking might like this little Lego sculpture of the man.

And for Mark, how about a secret office beer refrigerator?

Thursday, September 13, 2007

I suppose living in Taumatawhakatangihangakoauauotamateapokaiwhenuakitanatahu would be worse than living in Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch

Why is this the worst place name in the world? In Maori, the native language of New Zealand, the “wh” sound is pronounced “f”. Say it aloud in your office and see what happens.

The 22 Worst Place Names in the World

Courtesy of Mark comes this list of badly named places in the world. Number 8 is where my parents got married. And what place is number one?

You'll just have to read and find out …

Friday, September 14, 2007

Yet more notes on a Greylist implementation

It was bad enough getting up early this morning to cover the phones (Smirk and P were heading out of the area for several meetings) but to wake up to a customer (who had gotten my cell phone number when I called him yesterday) complaining about bandwidth issues (and yes, their 100Mbps connection is slower than a 56Kbps modem) made it all the worse.

After dealing with that issue (turned out to be a problem with The Monopolistic Phone Company, but it took several hours to diagnose that problem) I turned to what I had originally planned on doing today, working on the greylist daemon.

I managed to fix the problem with fork(). The code I used for this daemon I borrowed from a previous daemon, which set each open file to be closed when calling exec(). I removed that code, it worked on the server. I'm not calling exec() (I am calling fork(), but I don't know why marking files to be closed on exec() would have an ill effect, but it did, so it went).

Go figure.

I also wrote an interesting frontend to the daemon, which is called gld_mcp (short for “Graylist Daemon Master Control Program”). Prior to this, I had to send a variety of signals (as root—otherwise I don't have the appropriate permissions), and check the system log files to get any information out of the daemon. Now, I can do:

gld-mcp>show stats

Start:             Fri Sep 14 20:58:16 2007 
End:               Fri Sep 14 21:10:37 2007 
Running time:      12m 21s
Tuples:            33
IPs:               46
Graylisted:        14
Whitelisted:       19
Graylist-Expired:  0
Whitelist-Expired: 0

gld-mcp>

without having to be root or grovelling through system log files. (By the way, the IPs: field is the number of entries in the IP whitelist; any email coming from an IP address that matches an entry in this table is automatically let through)

Since I changed the program to check the creation time instead of the last access time, only a few more spams have gotten through, but the issue of maybe never getting a legitimate email has gone away, which is good.

And it wasn't a totally bad day—at least the phones were quiet.

Monday, September 17, 2007

Mea culpa

Today felt like a Day Ten. Went to bed around 5:30 am (which is my usual bedtime) only to get a call at 10:30 am from Smirk about a problem, and had to drive to Boca Raton to get it resolved (normally, I get to work from home).

Looking back at it, I've had worse days. It wasn't like I was dealing with obsolete computers from Hell, or on a business trip from Hell, or even dealing with Russian hackers from Hell breaking into a server during a hurricane. Nope, nothing quite as bad as any of that.

But it was my fault for getting that call after five hours of sleep at the ungodly hour of 10:30 am, and because it was my fault, that made it all the worse. To make me feel even lower, the issue itself was resolved rather quickly (instead of being handled on Friday, when I said I would handle it—sigh).

Tuesday, September 18, 2007

“So think twice before you assume … ”

I don't believe this.

How can someone with otherwise perfectly normal hearing not know their notes?

If you can do X, why can't you do Y? (this is actually a quote from the video on the page)

Years ago I was hanging out with my friend Eve when the conversation turned towards Microsoft Office and her wanting to learn how to use the program more effectively.

“I need to see if there's a class I can take,” she said.

“Class?” I said. “Just sit down and play around with the program.” It seemed a perfectly reasonable approach to me. Why waste money or time on a class?

“I can't do that,” said Eve. “I won't learn.”

“What?” That was just silliness. I have never heard of such a thing. “Can't you just sit down and do it?”

“I don't know how to do it, that's why I need the class.”

“How hard is it to load up Microsoft Word and start playing with it?”

“When will I find the time?”

“Yet you'll make the time for a class?”

“Yes. Besides, I learn best when someone tells me how,” she said.

It was my first real experience with different learning methods. I had a hard time fathoming that an otherwise intelligent person (who could program computers) couldn't learn on their own. Heck, that's how I learned most of what I know, and people have always told me I was intelligent. QED anyone intelligent can teach themselves.

What I've learned since is that not everyone can teach themselves. And that there are more learning styles than just self-teaching and lectures. A lot more. And furthermore, I learned that just because I do something one way doesn't mean that other people do something the same way.

The video demonstrates that point succinctly.

Wednesday, September 19, 2007

“Things happen at sea.”

Oh, is that today? I guess so.

I think that Eric Burns had the best take on talking like a pirate.

Arg.

Thursday, September 20, 2007

What next? Checking your Blackberry while bungee jumping?

What?

Living in a van
And driving it all across the country

Where?

Down by the River
Many rivers, actually. And lakes and mountains and ice cream stands.

Why?

To get away, see America, find the best city to live in, meet cool people, and blog about it all.

Via Instapundit, In a van down by the river

While I telecommute to work, and I like telecommuting, I think this is taking telecommuting a bit too far (then again, I'm not one for camping).

And they're not even the first ones to do this.

Friday, September 21, 2007

What the heck do they put in the water in Boston?

BOSTON—Troopers arrested an MIT student at gunpoint Friday after she walked into Logan International Airport wearing a computer circuit board and wiring on her sweatshirt. Authorities call it a fake bomb; she called it art.

Via Flutterby, MIT student charged with wearing fake bomb she says was only art

And upon further reading, she wasn't wearing the circuit board to make a statement about airport security theatrics, but to gain attention at a career day at MIT, and was only at the airport to pick up her boyfriend.

Just below the masthead up there, I've written “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.’” At the time, I didn't like Boston because it's old (you really have to look to find anything in South Florida build prior to the 1960s, and as a result, most every building down here is “modern” in that it was initially designed with bathrooms, decent electrical and more importantly—air conditioning!), cold (water freezes down here at 40°F) and a twisty maze of one-way roads all alike (not to mention the drivers—think we have bad drivers? Hah!).

But this crap? This, along with the Mooninite scare, the Traffic Counter scare, mandatory health insurance (and if you don't have it, you pay even more in taxes) and hypocritical liberal weenies, has dropped my opinion of Boston even further.


Software performance with large sets of data

I have seen this many, many times. Something that runs fast during development and maybe even testing because the data used in testing was too small and didn't match real world conditions. If you are working on a small set of data, everything is fast, even slow things.

Software performance with large sets of data

The primary test I use with greylist daemon is (I think) brutal. I have a list of 27,155 tuples (real tuples, logged from my own SMTP server) of which 25,261 are unique. When I run the greylist daemon, I use an embargo timeout of one second (to ensure a significant number of tuples make it to the whitelist), a greylist timeout of at least two minutes, with the cleanup code (which checks for expired records and removes them) running every minute. Then to run the actual test, I pump the tuple list through a small program that reformats the tuples that the Postfix module expects, which then connects to the daemon. There is no delay in the sending of these tuples— we're talking thousands of tuples per minute, for several minutes, being pumped through the greylist daemon.

Now, there are several lists the tuple is compared against. I have a list of IP addresses that will cause the daemon to accept or reject the tuple. I can check the sender email address or sender domain, and the recipient email address or domain. If it passes all those, then I check the actual tuple list. The IP list is a trie (nice for searching through IP blocks). The other lists are all sorted arrays, using a custom binary search to help with inserting new records.

Any request that the server can handle immediately (say, checking a tuple, or returning the current config or statistics to the Greylist Daemon Master Control Program) are done in the main processing loop; for longer operations (like sending back a list of tuples to the Master Control Program) it calls fork() and the child process handles the request.

I haven't actually profiled the program, but at this point, I haven't had a need to. It doesn't drop a request, even when I run the same grueling test on a 150MHz PC).

I just might though … it would be interesting to see the results.

Saturday, September 22, 2007

Software performance after a few hours with large sets of data

As a corollary to yesterday's entry about testing—make sure you test for several hours.

I found a bug in the latest version of the greylist daemon that only manifests itself after about six hours of running. For some as yet unknown reason, the program just stops responding. It doesn't segfault (if it did, it would automatically restart). It just doesn't quit (if it did, I wouldn't see it running in the process list). It just gets into a weird state. When I attach gdb to the running instance the stack frame is somewhere in the weeds (that's a technical term) so its hard to isolate the problem.

This type of bug is very difficult to diagnose.

Although I do have an idea of what it might be. The latest feature (as a request by Smirk) is to checkpoint the program every hour or so—it dumps its internal state so it can pick up again when it restarts. When I checked the logs, the last two times it crashed (after running for about six hours) it was just as it was checkpointing itself (which is logged).

I removed the checkpoint feature from the “production” version, and hopefully, I won't get another influx of spam in six hours (the Postfix module accepts the incoming email if it doesn't get a response from the greyist daemon after five seconds—I figure a) it's better to receive spam than lose email and b) getting a ton of spam is a clear indication something is wrong).

Meanwhile, I'm running the grueling test slowly (one tuple per second), with the hopes of triggering (or at least, reproducing the problem) in six hours.

Sunday, September 23, 2007

Heisenbugs

That weird bug that shows up after a few hours is proving hard to find. I've been running the greylist daemon for over a day now on my development server and have yet to reproduce the issue.

But it does relate to the checkpoint feature, because since I disabled that particular feature on the production server, it hasn't stop working.

Very strange indeed.


I think this was already done by John Titor

Guys, it's time for

Pretend to be a Time Traveler Day

You must spend the entire day in costume and character. The only rule is that you cannot actually tell anyone that you are a time traveler. Other than that, anything's game.

Via Les Orchard, Pretend to be a Time Traveler Day

In this instance, if everyone does it on December 8th, 2007, then it loses its significance, especially in light of John Titor, who showed us all how to pretend to be a time traveler way back in 2000.

Monday, September 24, 2007

It's really been over ten years since I wrote “An Extended Standard for Robot Exclusion”? Wow …

Around the same time the IETF draft was being discussed, Sean “Captain Napalm” Connor [sic] proposed his own extension to the Robots Exclusion Protocol, which included Allow rules as well as regular expression syntax for rules, and new Robot-version, Visit-time, Request-rate, and Comment rules. Less than 100 of the sites I visited use rules unique to this spec.

Via email from Steve Smith, robots.txt Adventure

[As a small aside, I don't know why people insist on spelling my last name with an “O-R” instead of an “E-R”. It's not like I misppelled my own name on that page. Sigh. —Editor]

That's not the only place “An Extended Standard for Robot Exclusion” has been referenced—it's also mentioned in O'Reilly's HTTP: The Definitive Guide, but until Steve reminded me of it, I basically forgot about it. Understandable since the last time it was edited was November of 2002 (and even then, the previous time it was edited was six years earlier—it's old).

This probably means it's time once again to check the links and make sure they all work.

And maybe clean up the HTML while I'm at it.

Just as soon as I can reproduce that insipid Heisenbug.


Probing further into Alien Abductions

Today, this very day, forty-six years ago, Betty and Barney Hill drove down U.S. 3, right past my house and into history. They were about to become Patient Zero for Alien Abductions with Weird Medical Experiments, Missing Time, and Big-Eyed Extraterrestrials. The first and (we are told) best documented case of Alien Abduction Evah. There was a book. There was a made-for-TV movie. Magazine articles. Mentions in other books. Cl ose Encounters of the Third Kind. X-Files.

So what happened out on Route 3?

Via columbina, Alien Abduction

I'm guessing that this debunking article won't go over very well in Rachel, Nevada. It's also long, but well worth reading since everything about the Betty and Barney Hill abduction is debunked.

I also found it helped to use Google Maps to help follow along on that fateful roadtrip forty-six years ago.


Heisenbugs, II

I spent several days testing the greylist daemaon on the development server, and could not for the life of me reproduce the crash. I cleaned up the code a bit, and again, I couldn't get the program to crash on the development server.

Moved the latest version to the production server, with the checkpoint feature enabled, and after a few hours (about 4½ hours this time) it froze.

Disable the checkpoint feature, and it runs fine on the production server.

I'm giving up on this bug hunt for now. The program saves its state when it stops running—the only way we'll lose the state is if the server it's running on suddenly loses power, and if that's the case, then we have more issues to worry about.


Our wall has been framed!

I suddenly heard a large amount of pounding. I went out to find not The Kids making all that noise, but Spring. She was busy hanging up a metric buttload of pictures in the living room.

[My God!  It's full of frames!]

The whole wall was covered in pictures and paintings (well, one painting). I like the effect—it makes the living room look taller. (For those who are curious, most of the pictures in the brown frames are pictures I took, along with the alligator and the Everglades, which are on either side of the large image, which is an Ansel Adams print. The blue painting was given to The Kids by an aquaintence of ours. At the very far end are pictures of The Kids and a few certificates)

Tuesday, September 25, 2007

Abstraction for its own sake

This is a rather small and unfocused rant on unnecessary abstractions. It may be related to this wiki page on abstraction not scaling; it may not be (told you this was unfocused).

I'm in the process of writing the Sendmail interface for the greylist daemon, and as far as that goes, it's very simple for this application—it just requires the writing of four functions, one that's given the IP address of the remote SMTP server, one that's given the sender email address, one that's given the recipient email address, and one to clean up any resources allocated from the other functions.

Like I said, pretty easy and straightforward.

The oddness comes in the first function's definition. It's:

sfsistat xxfi_connect(SMFICTX *ctx,char *hostname,_SOCK_ADDR *hostaddr);

The _SOCK_ADDR variable contains the IP address of the remote SMTP server. What is it? I dunno. What does it contain? I dunno. All I care about is the actual IP address, and I presume it's somewhere in this variable (most likely a structure of some kind). But there's no further API for pulling any useful information out of this _SOCK_ADDR.

Well, let's dive into the header files:

#ifndef _SOCK_ADDR
# define _SOCK_ADDR     struct sockaddr
#endif /* ! _SOCK_ADDR */ 

For some reason, the writers of Sendmail felt it prudent to hide the definition of the IP address behind another name. Presumably to make their code more portable to other non-BSD-derived network stacks that don't use struct sockaddr to store IP addresses.

But that does my code no good. I don't care about the hostname, I care about the IP address, yet without further information, I don't know exactly what I have. Is it the binary form of the address? How big? (there's IPv4, in which each address is 32 bits long, and IPv6, in which each address is 128 bits long) I had to dive into the header files to find out what exactly I'm given.

And it's not like the above definition of _SOCK_ADDR is wrapped around other #ifdef's checking for various operating systems or network stacks. The above definition is it! That's all there is.

So I really have to wonder why they felt this further abstraction for their code was necessary. It seems to be abstraction for abstraction's sake. Here's a hint: you aren't going to need it.


Reason #98,333,323 why I hate control panels

[The following is a trouble ticket submitted by me into the Company Internal Trouble Ticket Queue System™. It should be of no real surprise to anyone here, but it still makes for decent blog fodder.]

I have the graylist sendmail module written, so I go to install it for the XXXXXXXXXXXXX domain. The initial module does nothing but log the requests and let the email through—I did the same for the postfix module to ensure that the module worked before hooking it up to the greylist daemon.

Anyway, I'm going to install the sendmail module for XXXXXXXXXXXXX. XXXXXXXXXXXXX is on XXXXXXXXXXXXXXXXXX, which is a box managed by Insipid. Now, the instructions for installing the sendmail module are easy—just modify /etc/mail/sendmail.mc with the following lines:

define(`_FFR_MILTER', `1')dnl.
INPUT_MAIL_FILTER(`filter1', `S=unix:/tmp/milter')

And run make in /etc/mail to generate the new sendmail.cf file. Fortunately for us, I made a backup copy of both the sendmail.cf and sendmail.mc files. So I do thusly. And then I compare the new sendmail.cf file with the one supplied by Insipid.

[root@XXXXXX ~]# cd /etc/mail
[root@XXXXXX mail]# diff -y sendmail.cf sendmail.cf.milter

(if you run that, make sure your terminal window is W I D E, since it shows both versions side-by-side)

Lots o' differences.

And while I can merge the two, will an upgrade of Insipid break sendmail.cf? What about our warranty? Or are we forever doomed to manually patch the sendmail.cf file?

Wednesday, September 26, 2007

“You mean there's someone just as good as Carl Barks?”

I grew up reading Uncle Scrooge, but by the time Don Rosa started drawing the comic, I had stopped reading comic books in general. And while I had heard of Don Rosa as an Uncle Scrooge artist, I had no idea how good he was, in both art and story.

I might have to scare up a few copies of his work.


How much money can I get with my vote?

A democracy cannot exist as a permanent form of government. It can only exist until the voters discover that they can vote themselves money from the public treasure. From that moment on, the majority always votes for the candidates promising the most money from the public treasury, with the result that democracy always collapses over loose fiscal policy followed by a dictatorship.

Alexander Tyler (presumedly)

There are two ways out of this: inflation or deflation. Either home prices drop until they return to their historical relationship to wages, or the price of everything except houses goes up as the Federal Reserve and Congress bail out “homeowners.” The Federal Reserve can do it with its current chief's money-dropping helicopters, or Congress can do it by using our tax money to pay off the bad debts of investment banks while pretending to “bail out homeowners who will lose their homes!” Either way, we taxpayers lose and banks win.

The coming mortgage bailout

Hmmm … democracy … or fiscal irresponsibility?

Yeah … democracy is overrated anyway.

Charge it! I won't have to pay for it! Woot!

Thursday, September 27, 2007

Toccata and Fugue in D Minor

For Bunny: a neat way to see Johann Sebastian Bach's Toccata and Fugue in D Minor.

Yup. See.

As well as hear.

It reminded me of the last half hour or so of Close Encounters of the Third Kind, only without the aliens and French directors running about.

Friday, September 28, 2007

And by the way, I agree that we shouldn't beg the government for a handout

[In a long back-and-forth exchange between Gregory and myself, I posted the following, which I'm posting here as well.]

There were two comments to How big a problem is lack of health insurance? that really stood out for me. The first one:

A few points. I lived under socialized medicine in England and it is no panacea. The rationing of medical care is ridiculous and they keep ever increasing amounts of money into a system that is failing. Moore extols virtues and buries the vices of the system.

As to insurance, we really have no agreement about what is health insurance and what should it provide. Is it to protect people financially from catastrophic illnesses? Provide all medical care no matter the illness? Cover only those illnesses/services you want from a menu of options? For instance, one would think a gay man isn't interested in maternity care for him (and his partner).

Until we agree on the terms, this debate will be divisive and solve little. But politicians will continue bloviate regardless through this election cycle.

And the second one:

I found this comment hilarious.

“Not just one, but every other industrialized country manages to cover everyone, including all children, while having much lower costs and, by most measures, better health outcomes and more preventative care. It's no big mystery.”

The British system recently admitted to rationing of care. Many people have been hurt by that. Some have even died.

In Canada, diagnostic tests are often delayed for months. In some cases this means that the patient will die before getting properly diagnosed.

The reason why other systems have lower costs for drugs is because their governments mandate those costs and Americans subsidize them by paying higher prices for the same drugs.

I think we need to start questioning why health care is so expensive. And not just here, but in the West in general (why else would England ration healthcare?).

Where's the money going? I'll be looking at three aspects of health care in an attempt to figure out why it's so bloody expensive (pardon the pun).

The Student,
The Resident
and the Doctor

I start, with the doctors.

Becoming a doctor requires at least a decade of schooling. Four years of pre-med, four years of medical school, one year of internship, and three years of being a resident. And eight years of schooling isn't cheap. Anywhere from $100,000 to $240,000 total (reference, reference). Student loans seem to average about 10% interest rate (reference) so it's basically similar in cost to a mortgage (but without the benefit of selling it to someone else if things go rough). So your average doctor is facing nearly $200,000 of debt just for the honor of being able to say “cough for me please … okay, take these pills and call me in the morning.”

That in itself limits the number of doctors available, and if you remember Economics 101, if the supply remains constant yet the demand goes up, so does the price. And in this case, the supply is restricted.

Salaries for doctors appear to range $112,000 to $360,000 per year, depending upon speciality and skill, with an average that seems to be around $230,000/year (although I didn't actually calculate that, it seems right).

So our doctor now makes $230,000 a year (I suspect not for a newly graduated doctor, but hey, let's be generous). Assuming an average of $200,000 in student loans at 10%, being paid back over 30 years (and I have no idea if this is realistic, but it's a ballpark figure) that means the doctor is paying around $1,760/month in student payments. That works out to 11% of his income. His income tax bracket is 33%, so now we're up to 44% of his income is already spoken for before he can pay his mortgage.

Oh, then there's medical malpractice insurance.

Some quick searches (reference, reference) seem to place medical malpractice premiums between $15,000 and $18,400 a year. Split the difference and we get $16,700 a year (and probably way higher for obstetricians) which is another 7% of his income removed (we're now up to 51% of our doctor's salary gone before he can use it).

No wonder doctors make five figures a year—otherwise, they can't afford to be doctors!

The Man,
The Plan,
The HMO

Assuming you have health coverage, you don't pay for it.

Oh, you may pay some token amount like $20/visit, but otherwise, who cares what the price is? You're not paying it, your insurance is.

You don't select doctors, clinics or hospitals on the basis of price, but on the primary basis of “is he/she/it listed in the little black book of allowable doctors/clinics/hospitals,” secondarily on “which one is closer” and lastly on “which doctor/clinic/hospital on that list do I like the most/hate the least?”

Notice that price isn't among the factors here.

Sure, you'll get a bill and see the price the doctor/clinic/hospital charged the insurance company and you'll go “Whew, glad I have insurance to cover that!” And you may have to bitch argue a bit with the insurance company to actually pay that amount.

But generally, price isn't a primary consideration.

Until you don't have insurance, but that's what we're arguing about here.

I digress.

If you were handed a bill for $225 for a few ankle X-rays (reference) and had to pay it out of pocket, you might really start questioning the doctor for his outrageous fees; considering that you used to get foot X-rays for free at shoe stores, you might just tell the doctor where they can shove those ankle X-rays. At the very least, you probably won't be going back to that doctor any time soon. And possibly most people. The doctor may then have to rethink the $225 price, and drop it to get customers back in the door.

The insurance company, on the other hand, just shrugs and pays the $225.

But why does an ankle X-ray cost $225? Part of it is because that's what the insurance companies can bear to pay. Another part is the administrative overhead the doctors/clinics/hospitals have to go through in order to get money from said insurance companies (reference, reference). A doctor will have to have extra staff (even if it's just one overworked person) to handle just the paperwork.

Again, these costs are passed on down.

The insurance company just shrugs and pays.

And if the insurance company will pay $225 for an X-ray, why not $300?

We shrug and go “whew, glad I have insurance to cover that!”

The insurance company shrugs and pays.

And in the end, we pay.

The Pharms,
The FDA
And the jagged little pill

It's been claimed that pharmaceutical companies make too much money at the expense of the sick, and while there may be some truth to that, it's also true that it's hideously expensive to bring new drugs to market. And a major portion of that is the testing required by the FDA (reference, reference, reference, reference, reference, reference, reference, reference). More clinical tests mean more money spent, and more time spent, before a pharmaceutical company can market and hopefully recoup its development costs. And forget profits, just breaking even is difficult enough. And you might think it would be easy for a pharmaceutical to recoup its development costs in twenty years (the length of a patent giving exclusive rights to the patent owners), but I'm guessing it depends upon how popular it is (or how common the ailment it cures or prevents).

It also doesn't help that other countries outside the US set caps to what the pharmaceutical companies can charge, and it becomes even harder to recoup the development costs (and this gets back to the comment above, where the US subsidizes the cost of medicine elsewhere by charging more domestically).

The Uninsured,
The Illegals
And justice for all.

An emergency room cannot turn anyone away, therefore, those who can't get insurance for whatever reason often head there to get treatment. And since most can't pay, the hospital has to subsidize the costs of the emergency room with higher prices elsewhere.

So there you go. It's expensive because it's expensive to have doctors. It's expensive because we aren't price sensitive. It's expensive because drug testing is expensive. It's expensive because a lot of people don't pay. It's expensive because of half a dozen other reasons I forgot to mention.

Is there a fix?

I suspect there is, but it's probably one that nobody will like.

Saturday, September 29, 2007

Revisions of versions

I spent today making sure I was using the lateset version of the greylist daemon across two production servers (one running Postfix; the other Sendmail) and the development server (or rather, servers as I actively develop on two different machines).

Good thing too, because there was one file that was completely different on each machine, and quite a few files that were the same on two or three and different on the remaining machines.

You might ask why I'm not using some form of revision control, but I am. Only I don't think it's right for how I work. I could use CVS, since it comes already installed on Linux distributions, and I'm currently using it for mod_blog. But it does have a few problems. Then there's subversion, but the last time I checked, it was a bear to install, and I'm not sure how one actually goes about creating a new project with it.

No, for this project, I decided to try git. Dead simple to install. Dead simple to create a new repository. Dead simple to create and checkout different branches. Incredibly fast too. But managing a central repository with git seems to have eluded me. Perhaps it's because I don't fully understand how git is used properly, or perhaps it's because I want a centalized development model, not a decentralized one (even though I do development across different machines). And the pulling or pushing of changes from one repository to another doesn't seem to work as I would expect it to work.

It's a pity, because other than “checking in” and “checking out” revisions, it's a nice, fast program.

Sunday, September 30, 2007

I would still like to try this at some point

Every other Sunday I get together with a group of friends for a day of RPGing. This week three of our seven member gang bowed out. Jeff, the current GM mumbled something about running a one-shot in a different system. I was hoping to get the chance to try out Risus: The Anything RPG, because at six pages (and that's including the optional advanced rules) it seems perfect for those occasional one-shots.

Alas, at the last minute, Gregory bowed out and with so few people left to get together, today's game just fell apart.

Ah well.


The Overnight Millionaire

Bunny recently received an 88 page booklet in the mail called The Overnight Millionaire by Russ Dalbey, which outlines three easy steps to making money hand-over-fist.

I scanned through the 88 page booklet. It's not until page 13 that Mr. Dalbey mentions what the scam plan is based upon—the “Cash Flow Note” business. It's basically matching sellers of “notes” (read: mortgage), who're currently receiving monthly payments (say, on a house) but want to cash out, to buyers of “notes,” investors who want a steady stream of monthly income.

So the “three easy steps” are (starting on page 37):

  1. Find note sellers.
  2. Find note buyers.
  3. Introduce the two, getting a cut of the action.

Easy.

But then again, so is writing a metasearch engine.

Amusingly enough, as of today, the top result in Google for “The Overnight Millionaire Russ Dalbey” is Russ Dalbey—Winning in the Cash Flow Business Complaints.

Heh.

It's amazing that in the age of Google scam artists can remain in business.

Monday, October 01, 2007

Beating on the dead horse that is health care

Gregory had a few quibbles with the “The Man, The Plan, The HMO” section of my health insurance rant of the other day (I think he didn't like the “Oh, you may pay some token amount like $20/visit, but otherwise, who cares what the price is?” bit).

Even Bunny said I got some details wrong in this section, saying that insurance companies don't just shrug and pay (Gregory said the same thing). She said that the insurance companies have a concept of a “normal price” for each service and can refuse to pay the doctor's (or clinic's or hospital's) but counter with what it thinks is the correct amount to pay. The doctor (clinic/hospital) can then either accept this counter offer, or go after the individual who had the service to pay the bill.

I don't think that Gregory's or Bunny's critiques change my main point in ths section all that much—that price is not the primary selection criterion when selecting a doctor (clinic/hospital).

I received another comment, commenting on this bit from Gregory:

Y'know, I was re-reading this entry and thinking about my good buddy PipeWrench, who is a very conservative Republican. He believes (as most Republicans do) that we Americans are responsible for ourselves and we should be going out and buying our own insurance and not begging the government for a handout.

Sadly, while PipeWrench is in the majority of people in this country who have health insurance, he is in an extremely small minority when it comes to the worldwide population of industrialized nations. People from Canada, or most of Western Europe would listen to his ideals and then look at him like he was completely nuts.

Increasingly, most Americans nowadays would look at him like he was nuts, too …

I'd like to ask PipeWrench if he'd like to shell out that kind of money on his own without any kind of health coverage, or save up that money just in case he happens to get hurt. But I've learned my lesson not to engage PipeWrench in discussions of a political nature. I like him and want to keep him as a friend.

While PipeWrench didn't respond (he doesn't really use the Internet all that often) his girlfriend did (at LiveJournal, reproduced here because once the entry rolls off the feed, so does the comment at LiveJournal):

I think you know I agree with your political views for the most part. This was very well worded. I happen to look at the link to Greg's journal, where he mentions PipeWrench and politics in the same entry, lovely. To answer his question … yes PipeWrench would pay for his own hospital stay. He almost paid more than twice that amount to have his spine fixed at a different hospital, but his doctors talked him into one in his network for various reasons. Oh, and shock! He does save up money for emergencies. PipeWrench is not a hypocrit, sorry to disappoint.

“Well, there it is,” as Emperor Joseph II is wont to say in Amadeus.

And while I'm beating a dead horse here, my entry also spawned some interesting comments at Flutterby.

Tuesday, October 02, 2007

Next time, I should stick around long enough to find out the name, the scam, and how much money it'll cost me to make money

“Hello? Hello?”

“Hey there Sean.”

“Hello.”

“You signed for information on becoming financially independant and I'm wondering if you are interested in making money.”

“I'm sorry, but I'm not interested at this time.”

“What? You don't want to make more money? Everybody wants to make more money.”

“I'm sorry, I'm not interested at this time. Especially when it's on my cell phone.”

“But Sean, this is the number you gave me.”

“Be that as it may, I'm not interested at this time.”

“So, you'd rather be a loser?”

“Yes, I'm a loser who is not interested in your meth—” Click.

Wednesday, October 03, 2007

Workaround for a Heisenbug

Okay, now I'm concerned. I'm now running the production greylist daemon on an actual server (not a virtual server) with the checkpointing feature enabled, and it's working. That can mean one of two things:

  1. There's a bug in the virtual server environment that my program tickles
  2. There's a bug lurking in my code that the virtual server environment tickles

Neither one is good, and it's bugging me that I don't know which is the case. But I managed to at least work around the problem in the meantime (now watch—the bug is in my code, but it's the virtual server environment that causes the bug to surface after a few hours instead of a week or so it might take on a physical server).

Thursday, October 04, 2007

Swimming with sharks

I just watched Maxed Out (link via coell via Spring), a documentary on the debt industry (credit cards companies, banking institutions, etc.) and how it's in their interest to offer incredible lines of credit to those who can't really afford it since they'll be paying off forever (one example brought up in the film, for every dollar a credit card company attempts to collect, only 33¢ is for the principle—the rest is interest and late fees).

I'm of mixed minds on this. I think it's horrible what the credit agencies have done to the people interviewed in this documentary (half were deep in debt, the other half had family members who committed suicide because they were deep in debt), seducing them with loose credit and no way of ever paying it all off. On the other hand, these are corporations we are talking about, and if by 18 you haven't learned that corporations are out for themselves (or their shareholders if they're public companies) then maybe you should learn it the hard way.

How far should we as a society go to protect ourselves from our own stupidity?

I can see those who don't speak English, or have learning disabilities as sucessfully sueing these companies for fraud; but if you can read and write English, then no, it's your responsibility to read the fine print, since by law, they do have to spell it out (even if it's 10 pages at 8pt).

Friday, October 05, 2007

It's not quite as cool as a house made out of an old jetliner, but it's probably more affordable

For Gregoryfurniture made from aviation salvage (via Instapundit).

Saturday, October 06, 2007

Another look at Federalism—you know, how our government was originally designed?

And when the Fed's ban sex toys? Where do you go then? Sure, it's nice when the Feds enforce the laws you like, but what do you do when they enforce those you don't?

It's true that, left to their own devices, some states are going to choose some laws that are more restrictive than the laws Feds might enforce. For example, I think CA would have much more restrictive gun laws. Many Southern states would probably ban abortion.

However, it's much easier to reform and escape state law than it is to escape or reform Federal laws.

If we had a more federal system, marijuana would be completely legal in many states, and perhaps harder drugs as well. You might be able to buy a silencer without a FFA license in others.

Advocates of liberty would also be able to point to real life examples of American communities that are working just fine, despite the legalization of drugs/machine guns/prostitutes, instead of hypothetical examples, or distant foreign experiments that most people will never see.

In a more federal system, states would also have to compete for people more fiercely. Want high tech/bio tech businesses to locate in your state? Anti-abortion, anti-gay statutes are going to be a big turnoff to the employees (and hence, the employers) of such companies.

People would be more free to choose which legal regime most closely matched their preferences. If you wanted to live where abortion was legal, live in CA. If you wanted to shoot machine guns, choose WY or ID. Want to do both, move to NH.

Compare that to what you would have to do to escape oppressive federal laws. One route would be to move to a completely new country, which would require you to leave behind friends, family, and business contacts. You would also have to surmount language, cultural, and legal barriers to immigration.

Or, you could spend decades waging a campaign to reform the law at the federal level. This would probably require millions of dollars, and the cooperation of thousands of people to wage, with no guarantee that you would ultimately succeed.

A more federal system might not mean a more libertarian society on a given issue, in a given state. But overall, I think it would result in greater practical freedom for those who want it.

comm ent about States' Rights & Alabama sex toys at Flutterby

I quote in full, since there's a better chance that the person I want to read this will read this.


“Son, there's not much left of the carcass … you can stop beating that horse now.”

In a continuing back-and-forth exchange, the Director of the Citizens Alliance for National Health Insurance piped in, saying, “For those of you with an interest in having a viable national health insurance system in the US in our lifetime, please visit www.HR676.org.”

I checked out the Citizens Alliance for National Health Insurance website and while the site answers a bunch of questions like “Why haven't I heard of this bill before?” and “Do we really want our health care system to be controlled by government bureaucrats?” while urging people to sign up, it does not, however, present the actual text of H.R. 676, nor links to the actual text of H.R. 676. Yes, it does link to the official website for H.R. 676, but the official website for H.R. 676 (run by Congressman John Conyers, Jr. (D)) doesn't have the actual text to the bill, nor a link to the actual text.

It's a weird omission from both sites, don't you think?

And it's not like it's not online or difficult to find online.

Okay, so I went the extra step to find the actual text to H.R. 676 and after reading it, I have quite a few questions that the Citizens Alliance for National Health Insurance haven't answered. For instance:

(a) In General—All individuals residing in the United States (including any territory of the United States) are covered under the USNHI Program entitling them to a universal, best quality standard of care. Each such individual shall receive a card with a unique number in the mail. An individual's social security number shall not be used for purposes of registration under this section.

H.R. 676 [109th]: Expanded and Improved Medicare for All Act

Since the bill states “individuals residing in the United States” and not “citizens of the United States,” am I to infer that this also covers aliens? Both legal and illegal? I don't have a problem with covering legal aliens residing in the United States, but I do have a serious problem with my taxes going to pay for the health care of a large number of illegal aliens who don't even pay taxes!

Taxes? Did I say taxes?

National health insurance will simply require participating members to pay a similar monthly health insurance premium, perhaps in the form of a tax (but it's still the same thing as a premium no matter what you call it**)

**Whatever they call it—It's very important to keep in mind that this is NOT an ADDITIONAL tax but a REPLACEMENT for current private health premiums.

Citizens Alliance for National Health Insurance

Sorry, premiums, which brings up another point—is this voluntary? If it is, I'll buy the Citizens Alliance for National Health Insurance argument that it's a “premium,” not a “tax.” But if this is involuntary, you can play all the language semantic games you want, it becomes a tax! (or outright theft as some would say) The bill doesn't say one way or the other, although Conyer's financing figures show it as a payroll tax of 3.3% on both employer and employee.

Which brings up another question—as someone who is self-employed, are my taxes going up 6.6%? (In case you are unaware, those who are self- employed pay 7½% Social Security tax as an employee, and 7½% (the so called “Self-employment Tax”) as employer! Again, it's not answered in the text, nor on the official website.

(2) FEE FOR SERVICE—

(A) IN GENERAL—The Program shall negotiate a simplified fee schedule that is fair with representatives of physicians and other clinicians, after close consultation with the National Board of Universal Quality and Access and regional and State directors. Initially, the current prevailing fees or reimbursement would be the basis for the fee negotiation for all professional services covered under this Act.

(B) CONSIDERATIONS—In establishing such schedule, the Director shall take into consideration regional differences in reimbursement, but strive for a uniform national standard.

(C) STATE PHYSICIAN PRACTICE REVIEW BOARDS—The State director for each State, in consultation with representatives of the physician community of that State, shall establish and appoint a physician practice review board to assure quality, cost effectiveness, and fair reimbursements for physician delivered services.

(D) FINAL GUIDELINES—The regional directors shall be responsible for promulgating final guidelines to all providers.

(E) BILLING—Under this Act physicians shall submit bills to the regional director on a simple form, or via computer. Interest shall be paid to providers whose bills are not paid within 30 days of submission.

(F) NO BALANCE BILLING—Licensed health care clinicians who accept any payment from the USNHI Program may not bill any patient for any covered service.

(G) UNIFORM COMPUTER ELECTRONIC BILLING SYSTEM—The Director shall make a good faith effort to create a uniform computerized electronic billing system, including in those areas of the United States where electronic billing is not yet established.

(3) SALARIES WITHIN INSTITUTIONS RECEIVING GLOBAL BUDGETS—

(A) IN GENERAL—In the case of an institution, such as a hospital, health center, group practice, community and migrant health center, or a home care agency that elects to be paid a monthly global budget for the delivery of health care as well as for education and prevention programs, physicians employed by such institutions shall be reimbursed through a salary included as part of such a budget.

(B) SALARY RANGES—Salary ranges for health care providers shall be determined in the same way as fee schedules under paragraph (2).

H.R. 676 [109th]: Expanded and Improved Medicare for All Act
(emphasis added)

How is this not nationalizing the health care system? As a doctor (not that I am one, but I'm asking as if I were one) how does this benefit me? Does my malpractice insurance go down? Is it eliminated? Am I still allowed to practice privately the same treatments that this bill covers? If so, am I allowed to charge less than the Federal mandated charges? More?

(a) In General—It is unlawful for a private health insurer to sell health insurance coverage that duplicates the benefits provided under this Act.

H.R. 676 [109th]: Expanded and Improved Medicare for All Act

As an insurance company, what about our existing policies when (if) this goes into effect? Do we still provide coverage under the existing policy? If no, do those portions of the policy become null and void? And does the insured get part (or all) of their premium back?

(c) Intent—Sums appropriated pursuant to subsection (b) shall be paid for—

(1) by vastly reducing paperwork;

(2) by requiring a rational bulk procurement of medications;

(3) from existing sources of Federal government revenues for health care;

(4) by increasing personal income taxes on the top 5 percent income earners;

(5) by instituting a modest payroll tax; and

(6) by instituting a small tax on stock and bond transactions.

H.R. 676 [109th]: Expanded and Improved Medicare for All Act

How odd, even the text of the bill uses the word “tax” instead of “premium.” It looks like a tax to me. And how do I know that the “modest payroll tax” won't balloon into an “unmodest payroll tax?” Amendment XVI of the Constitution passed because the income tax was guaranteed to be a 1–7%, but that was quickly modified.

As it stands right now, there're too many questions for me to be comfortable with this bill ever being passed.

Sunday, October 07, 2007

X11 is dead?

The X11 Desktop's (what you see to the left) client/server protocol is built-in. There's no need to use vnc in most cases!!

I have no idea why it is so hard for people to grasp the power of client/server graphic networking. It's simple. Easy. Transparent. And so enormously useful that innum erable projects use it to great effect, and if only more people would just turn X11's network support on, it would be a better world.

I can only imagine it's a conspiracy.

Legions of PHBs hunched over their laptops in 1989, saying: “THIS X11 CONCEPT IS TOO POWERFUL! Imagine a world where every cell phone, handheld, laptop, desktop, server and supercomputer in the world could run all their applications on each other over a network transparent protocol!

“There'd be no need to rewrite every application for every new paradigm. We'd stop having to support all the old ones in the field, too. Every app on your cellphone could run on your desktop! And every app on your desktop could run on your cellphone! Think of all the jobs that would be lost! Think of (my) children and my golf fees!"

X11 is dead, long live X11

The X11 Windowing System is something that's hard to explain to someone who doesn't normally use computers remotely, and thus it's even hard to explain why using a computer remotely is even desireable.

I was first introduced to X11 in college, most likely by my friend Ken, who regularly came barging into my office with “Hey Sean! You gotta see this!”

X11 was cool because the Computer Science and Engineering Department would regularly install neat programs, such as a little program called Mosaic that allowed one to view information on something called the “World Wide Web,” that I could use in my office (in the Math Department one floor below the Computer Science and Engineering Department), without having to go to the trouble of installing it on my own computer (well, it wasn't my computer, but I was the administrator of it).

I even learned how to use X11 to get the login screen from my office computer on the computers in the various Computer Science and Engineering computer labs if I was stuck upstairs for some reason (and I preferred my office machine, an SGI Personal IRIS 4D/35 with video-editing capability, over the run-of-the-mill Sun SPARCstations CSE used).

I don't use X11 in that way much anymore; I find very little need for remote running of graphical programs, but when I do, it's nice that I can.

Unfortunately, there's a perception that X11 has poor performance. And yes, compared to NeWS, X11 is very clunky. And the pretty 3D eye-candy of modern windowing systems leads to even more poor performance across the network.

Besides, Microsoft Windows was never designed with network transparency in mind, and thus, to get access to Windows programs remotely, you need something like VNC. The same goes for the Macintosh. And hey, if you have ported VNC to both Windows and Mac, it's not that much work to port it to X11.

Sigh.

Another part of Mike Taht's rant skirts around true peer-to-peer networking, which the Internet was about fifteen years ago, but now, what with Microsoft's poor record at security and a perceived lack of IP addresses, is no longer the case. IPv6 will supposedly fix that, with an address space large enough to give every atom in the universe its own address, but the change in the Internet infrastructure (at least in the United States) will be expensive, not to mention time-consuming, so don't expect it to happen any time soon.

Yet another sigh.

Updated on Tuesday, October 9th, 2007

Why VNC may be better than X11.

Tuesday, October 09, 2007

Montezuma's Revenge

Yesterday was apparently some sort of holiday but instead of celebrating the rape and enslavement of Native Americans I was in bed fighting off what can only be called Montezuma's Revenge.

I'm feeling much better today.

And speaking of Montezuma's Revenge, I think Spring might want to pick up a few of these for those times when Spodie is himself suffering from Montezuma's Revenge.


X11 is alive?

Mark send me an email replying to my post about X11:

From
Mark Grosberg <XXXXXXXXXXXXXXXXX>
To
sean@conman.org
Subject
Of X11 and remote access…
Date
Mon, 8 Oct 2007 13:36:10 -0400 (EDT)

Sean,

I read your blog post on how X11 is network enabled and thought you glossed over a very important point. See, X11 is network enabled in that it has this concept of a program is a client to a display. So yes, if I am at home I can run some program on my X11 machine at work and send the display over.

But VNC on X11 goes one step better. It's a bit like “screen” (a program I still use) but for graphical apps (something I rarely use). I can have my X11 desktop sitting in some virtual framebuffer somewhere, connect to it, interact with it, go home, re-connect and it is exactly where I left it.

The normal X11 networking model is such that I loose my program state every time I move around. At least for me, personally, I am the kind of person who maybe yearly reboots a computer such that I loose my working environment and I frequently move about to different locations.

So for me, VNC on an X11 desktop makes total sense (well, screen makes even more sense since my main UNIX box probably doesn't have enough RAM to make a virtual framebuffer).

Oh, and VNC is way faster too, especially TightVNC. You don't wait 6hrs for a window to pop up while they negotiate event masks and other nonsense that should not exist.

He does have a point, and it's one of the problems with X11—you can't redirect a window to another display on the fly. Or, at least, I don't know of a way to do that. It also depends upon how you work. Me? I don't tend to leave applications running for any great length of time (especially graphical programs) because I have this irrational fear that they'll just keep sucking memory up until the machine becomes unusable.


Help fight leukemia and lymphoma

Passing this on … Spring could use your help. Please donate to help her raise money for leukemia and lymphoma research. Every little bit helps.

Wednesday, October 10, 2007

“He stacks his dice.”

For Lorie, who does love her dice—a video of some sweet dice stacking moves (via Jason Kottke).

Thursday, October 11, 2007

A little lesson on i18n

Then your Russian translator calls on the phone, to personally tell you the bad news about how really unpleasant your life is about to become:

Russian, like German or Latin, is an inflectional language; that is, nouns and adjectives have to take endings that depend on their case (i.e., nominative, accusative, genitive, etc …)—which is roughly a matter of what role they have in syntax of the sentence—as well as on the grammatical gender (i.e., masculine, feminine, neuter) and number (i.e., singular or plural) of the noun, as well as on the declension class of the noun. But unlike with most other inflected languages, putting a number-phrase (like “ten” or “forty-three”, or their Arabic numeral equivalents) in front of noun in Russian can change the case and number that noun is, and therefore the endings you have to put on it.

He elaborates: In “I scanned %g directories”, you'd expect “directories” to be in the accusative case (since it is the direct object in the sentence) and the plural number, except where $directory_count is 1, then you'd expect the singular, of course. Just like Latin or German. But! Where $directory_count % 10 is 1 (“%” for modulo, remember), assuming $directory count is an integer, and except where $directory_count % 100 is 11, “directories” is forced to become grammatically singular, which means it gets the ending for the accusative singular … You begin to visualize the code it'd take to test for the problem so far, and still work for Chinese and Arabic and Italian, and how many gettext items that'd take, but he keeps going … But where $directory_count % 10 is 2, 3, or 4 (except where $directory_count % 100 is 12, 13, or 14), the word for “directories” is forced to be genitive singular—which means another ending … The room begins to spin around you, slowly at first … But with all other integer values, since “directory” is an inanimate noun, when preceded by a number and in the nominative or accusative cases (as it is here, just your luck!), it does stay plural, but it is forced into the genitive case—yet another ending … And you never hear him get to the part about how you're going to run into similar (but maybe subtly different) problems with other Slavic languages like Polish, because the floor comes up to meet you, and you fade into unconsciousness.

The above cautionary tale relates how an attempt at localization can lead from programmer consternation, to program obfuscation, to a need for sedation. But careful evaluation shows that your choice of tools merely needed further consideration.

Via Flutterby, A Localization Horror Story: It Could Happen To You

Yikes!

And I thought I was being clever when writing my own replacement for printf() that allowed you to refer to parameters by placement.

Okay, I'll have to explain that.

In printf(), you specify variables with a special code, such as “%s” for a string variable, “%d” for an integer:

printf("Hey!  I saw %d %s\n",count,object);

But the variable specifiers and the variables themselves have to match up. So, if I want to change the output from “I saw X blah” to “blah: X” I not only have to change the text, but the order of the parameters as well:

printf("%s: %d\n",object,count);

Also, if you wanted to print a value multiple times (and it sometimes comes up) you have to repeat that value:

/* helps to say this as Foghorn Leghorn */
printf("That boy is %s!  %s, I say!\n",adjective,adjective);

I got around that by separating the variable types and parameter positions from the format string:

my_output("i $","Hey!  I saw %a %b\n",count,object);
my_output("i $","%b: %a\n",count,object);
my_output("$","That boy is %a!  %a, I say!\n",adjective);

(okay, here, “i” denotes an integer parameter and “$” a string parameter. In the format string, “%a” refers to the first parameter, “%b” the second, and so on)

The idea was the ability to change the string without having to change any code, and to that end, I did quite well. What I didn't realize is that full i18n is hard. I mean, just beyond character set issues.

Man, I had no idea languages could be so crazy.

Friday, October 12, 2007

Spam from bogus IP space

Earlier today (okay, technically yesterday) I came across the concept of bogons, or IP address not officially allocated for use. They even provide a current list of non-routed IP blocks. Curious about the effect of using said list to block potential spam, I setup a test, consisting of 565,012 tuples (we've stepped up testing of the greylist daemon over the past week) previously processed (I'm keeping some extensive logs here), added the 6,803 IP blocks not allocated, and let it rip.

An hour and a half later, I had my answer.

Of 565,012 tuples processed, only 6,117 came from non-allocated IP space.

It's a little over 1%.

I don't think it's worth adding the non-allocated IP space to the greylist daemon. Not that it makes the daemon run slower, it's just that an IP list of that size takes up quite a bit of memory due to the trie structure used to store the table, and for such a small gain, I don't feel it's really worth it.


I guess he won't be extending anyone's mortgage by three inches anymore …

Who hated Tolstokozhev so much as to hire a hit man to assasinate him? Well, I guess you have about one billion e-mail users to suspect. Tolstokozhev was a famous spammer who sent millions of e-mail promoting viagra, cialis, penis enlargement pills and other medications. Links in these e-mails usually led to some pharmacy shop, which paid Tolstokozhev a share of its revenue. This is a well known affiliate scheme employed by spammers worldwide. Tolstokozhev is estimated to be responsible for up to 30% percent of all viagra and penis enlargement related spam.

Via Wlofie in email, Russian Viagra and Penis Enlargement Spammer Murdered

Well, speaking of anti-spam measures, that certainly works (not that I … um … condone … such actions). A bit messy, in both physical and legal aspects, but still, quite effective.

Update a few minutes later

Then again, it may be a hoax:


Some musings on parallelizing programs

Can you, in your favourite language, show me the easiest way to parallelise the following program (written in C)? I am just genuinely curious.

int gimme(int x)
{
  return x * x;
}

int main(void)
{
  int i = 2, j = 4;
  int a = gimme(i),
      b = gimme(j);
  return a * b;
}

Write Me A Small Program

In my ideal world, any compiler worth its salt would optimize (mostly through variable lifetime analysis and constant propagation) that program down to the following:

int main(void)
{
  return(64);
}

but the author's main point is—what languages today can easily parallelize that code? His point, on a massively parallel computer, the calls to gimme() are both independant of each other, and therefore can be computed at the same time (assume, for the sake of argument, that gimme() takes a bit more time to execute than a single function call and multiply).

And in an ideal world, a compiler should be able to figure out that gimme() is, for lack of a better term, a “pure” function (one that does not rely upon data outside of its input parameters and local variables). This also implies that thread creation is cheaper than it is today (or easier, which is another of the author's points), and that the compiler will take care of the messy thread creation details for me.

But even an ideal compiler won't take us very far.

I was thinking about this as I was running tests on the greylist daemon last night. The program maxed out at around 130 requests per second, and this on a dual-core 2.6GHz Intel Pentium system that hasn't even used swap space, so speed and memory isn't an issue (and remember, the greylist daemon keeps everything in memory).

But as written, the program only uses a single thread of execution. Could I not create two threads (one for each CPU in the machine) and double the speed?

Maybe, but the compiler won't help me much.

When a tuple [IP address, sender address, recipient address] comes in, the program scans a list of IP addresses which can accept or reject that tuple. If the tuple isn't outright accepted or rejected based on the IP address, then the sender address is checked, then the sender domain, then the recipient address, then the recipient domain. Now, those lists are, for the most part, read-only, so no coordination is required between multiple threads for read access.

The actual greylist itself? The program checks to see if the tuple [IP address, sender address, recipient address] already exists, and if not, adds it to the existing list of tuples. And that part, adding the tuple to the list, happens on just about every tuple that comes in. In effect, the tuple list is “write- mostly.” And to ensure a consistent list of tuples, you need to coordinate multiple threads when trying to update the list. And now you get into semaphores, and locking and dining philosophers

Messy stuff.

I suppose each thread could get its own tuple list to update, but then you have to ensure that any given tuple X always goes to the same thread. Easy enough I suppose, but it's not something that you can leave up to the compiler.

In fact, in an ideal world, an ideal compiler would be hard-pressed to automagically parallelize this program. Certain parts, maybe. But overall, it would required thinking how best to write the program to be parallelized in the first place.

Saturday, October 13, 2007

Heisenbugs III

Wow … ten days.

Of course, the greylist daemon only took about two hours to hang on the right set of physical servers.

So I have a very subtle bug in the code.

XXXX.


The Right To Arm Bears

We had finally arrived at the South Florida Fair Grounds. I found it amusing that the South Florida fair grounds are about as far north as you can get in South Florida and still be within the geographical region known as South Florida (which technically speaking, lies between the Jupiter Inlet to the north and Homestead along the southern border, the Atlantic Ocean along the eastern edge, and US-27, beyond which is swamp land).

“You'd think they would have put the Fair Grounds somewhere more central, like central Broward County,” I said to my compatriots as we headed from the parking lots to the gates.

“It could be worse,” said Bunny, using a phrase I commonly use right back at me. “You do know that the University of South Florida isn't even in South Florida?”

“Nice sense of irony,” I said.

As we passed beneath a sign that said “Thank you. Hope you had a blast” I had an epiphanous thought—I probably picked the wrong color shirt to wear today—red. But, I thought, at least the blood won't show.

And with that, we entered the South Florida Fair Grounds towards the Gun and Knife Show.

[The right to arm bears]

Guns everywhere. Glocks. Smith-Wesson. Mossbergs. Colts. Everthing from .22 to 50-calibre, and then some. The Younger was eyeing an anti-aircraft rocket launcher when Spring asked who could possibly use such a device. Someone nearby said it could be useful if you live next to an airport. The Younger turned and looked expectantly at his Mom.

“No,” said Spring. “Let's continue on.”

At the point the group broke. Spring went off chasing the Younger as he flitted from table to table. Scott stayed to talk to a merchant behind the table, asking about the finer points of Colt 45s with an extended barrel. Wlofie headed off to a booth selling survival gear, and Bunny went off on a mission—to find a collection of throwing stars, muttering something about Racoon Ninjas terrorizing her neighborhood and teaching them a lesson.

I myself wandered off, amazed at the variety of guns available. And frankly, I found most of them to look fake—more like plastic toys. And to my surprise, most of them were plastic! At least the pistol grips. The cognitive dissonance was too great—the guns in TV and movies looked more “real” than these very real guns in front of me. But pick one up, and the cognitive dissonance grew—these guns where heavy.

“Looking for anything in particular?” asked a gentleman behind the table.

I looked up to see him wobbling around on a Segway. “Um,” I said, more cognitive dissonance building up, “I'm just looking.”

“Okay,” he said. “But if you need any help, just ask.” And he wheeled down the booth to pass a fellow co-worker also on a Segway. I've been to plenty of computer related shows and never saw a Segway, much less two—no, make that three Segways.

Amazing.

I wandered off to parts elsewhere.


Books on modifying the firing mechanism on an AK-47 I expected. Books on martial arts I also expected. I could even see the rationale for conspiracy books ranging from the Illuminati, the Freemasons, JKF to 9/11.

I was not expecting New Age books on Atlantis, aliens and homeopathy.

But even that wasn't as out of place as books by Noam Chomsky.

Noam Chomsky.

Available at a Gun and Knife Show.

Hey, if a Russian can sell crystals at a Gun and Knife Show, why not Noam Chomsky at a book booth?

Cognitive dissonance.


A few hours later we all meet back outside. Bunny had been unable to locate sufficiently sharp throwing stars to tackle the Racoon Ninjas terrorizing her neighborhood. The Younger had procurred a gas mask for those times when it's his turn to change the litter box. Scott informed us that while he could tell us what he got, he would have to kill us afterwards. Wlofie had a big grin on his face, but declined to tell us what that was all about.

And myself? I had successfully survived the Gun and Knife Show in a red shirt.

Sunday, October 14, 2007

Random and a rather rambling musings on computing environments and the customization thereof

I'm not even sure where to begin with this. Or even where I'm going with this.

First off, there's Aza Raskin's demonstration of Enso, an application that brings the command line back to the GUI in a very novel way (and yes, the video is worth watching, and the Enso application is something that, were it available for either the Mac or Linux, I might buy).

I got the link to the video from Thought Storms: The Return of the Command Line, which I linked to before (and that post is somewhat related to this post).

This all somehow is all related, primarily to customizing the computing environment.

One small example: I have customized vi (the standard Unix editor) to my liking. It's not a lot of customization though. My .exrc file looks like:

set ai
set showmode
set sw=2
map m ^F
map v ^B

That's it. Five lines of modification. The first just sets auto-indent mode. The second one displays the current mode (command mode or insert mode) on the screen. The third sets the tab-indent to two spaces. Those, I can live with or without (and really, half the time, I don't want auto-indent mode so that's actually a wash).

It's the last two lines I can't live without.

The first maps the M key to page forward in the command mode. Normally, the “page-down” command is Ctrl-F but that's two keys to hit, and usually, when I'm in vi, I'm not editing, I'm viewing. And the last line maps the V key to “page-up”, which is normally bound to Ctrl-B (again, two keys).

And what normally happens is I get on some random server at The Office, I'm viewing a file in vi, go to hit M to page down through the document, and get … something else.

Then I go ballistic.

Sigh.

Which is one reason why I tend to type out insanely long command lines instead of making a script—because customizing the computing environment isn't worth my time or sanity (even with a five-line file; also, people using my customizations, one of which involves renaming rm to delete tends to drive them up a wall).

This also relates partially to my dislike of IDEs. I've learned to be productive without one, since I “grew up” without using them. And I've found them to be intrusive the few times I have used them (mainly beause the built-in editor sucked compared to what I was actually used to, which again, ties back into computing environment customization). I found it weird to hear programmers (mostly students) asking where they could get an assembly language IDE—they were totally lost without such a crutch (and yes, I'm using that word deliberately here). But my crutch was a particular text editor from IBM. Was it really that great of an editor? Maybe. This quote pretty much sums up how I felt about it (the quote is about a newer version of the editor I used):

Is PE II really that good? Frankly, no. It's just that I'm really that lazy. I've used it for so long that it's like breathing to me. I don't have to think about where the keys are or what they do. I just think about what I want to do and it happens.

When I need to edit a C file that is too large for PE II, I use Brief. Sure, Brief is bigger, better, and faster than PE II. But its key bindings aren't etched into my skull like the pattern on an old monochrome monitor that's been displayed for months.

But enough about that. I know what my preferred C/C++ programming environment is in DOS. I want to find my preferred programming environment in Linux. The reason I bring up my personal preference—and the inertia that cements it—is that I believe the same sort of inertia is at work among the developers I queried.

Linux development: Command Line, Emacs or IDE?

I used that editor long enough that I never had to “think” about using it. I just did. And I'm still attempting to use the Tab key for navigation to this day (under PE, the Tab key didn't insert spaces—it just moved the cursor to the next tab stop; I could navigate to any point on the screen in just a few seconds, if that).

So, to bring this back around to Enso—yeah, it's great. Yeah, I'm tempted to get it (if only it didn't run under Windows). But do I want it? Were I to become dependent upon it, would using a non-Enso enabled system suck too much?

What exactly do I want from my computing environment?

Seven months ago I brought my workstation home from The Office with the intent of replacing my old home system linus. But the amount of customization I've done to linus is so extensive, that I've yet to actually switch. Even though I can create entries for this blog technically anywhere (and submit it as a text file, or through email, or through a web-based interface) I still prefer editing on linus, as I have several extentions to the editor I use there to help create entries (and it's still not as fast or as smooth as I would like it).

Blah.


An Open Letter to Script Kiddies

Dear script kiddie,

I know, and you know, that if you have a web server with PHP, you have an exploit waiting to happen. It's axiomatic. And really, I'm okay with that.

I'm also okay with you uploading your crap to the server using said exploit. I like porn just as much as anyone else. And you really have some interesting stuff there (thus validating Rule 34 of the Internet).

You're even smart enough to wipe the source code after you start your nefarious program. Or you're smart enough to get programs that do that for you. Bully for you. Wonderful.

But let me give you one more piece of advice, and I mean this from the cockles of my heart, maybe below the cockles, maybe in the sub-cockle area. Maybe in the liver. Maybe in the kidneys. Maybe even in the colon. But it's a piece of advice you need to hear.

If you want your little hack to go unnoticed, and frankly, that's the point, isn't it? To do your little script kiddie thangs without being noticed, then please,

Stop sucking up all the CPU time causing the system load to shoot over 600 you XXXXXXX XXXXX XX XXXX!

Ahem.

Thank you for your consideration.

Monday, October 15, 2007

“I coulda had a V8!”

Valgrind.

Why didn't I think of that sooner?

Anyway, I installed valgrind on the virtual server and started up a test run to see if I could locate the current bug.

Not two minutes in, and I got the following:

==27967== Use of uninitialised value of size 4
==27967==    at 0x80508DF: crc32 (crc32.c:83)
==27967==    by 0x804A6C1: send_packet (main.c:566)
==27967==    by 0x80496FC: mainloop (main.c:151)
==27967==    by 0x80493A5: main (main.c:68)
==27967== 
==27967== Syscall param socketcall.sendto(msg) points to uninitialised byte(s)
==27967==    at 0x40EDFD1: sendto (in /lib/tls/libc-2.3.4.so)
==27967==    by 0x80496FC: mainloop (main.c:151)
==27967==    by 0x80493A5: main (main.c:68)
==27967==  Address 0xBEEDB2EA is on thread 1's stack
==27967== 
==27967== Source and destination overlap in memcpy(0x4251028, 0x4251028, 256)
==27967==    at 0x401D236: memcpy (mac_replace_strmem.c:394)
==27967==    by 0x804F00D: tuple_expire (tuple.c:231)
==27967==    by 0x804BC3D: handle_sigalrm (signals.c:278)
==27967==    by 0x804B6BF: check_signals (signals.c:50)
==27967==    by 0x80493BD: mainloop (main.c:83)
==27967==    by 0x80493A5: main (main.c:68)

I was mystified by that first warning, as the function in question isn't all that big:

CRC32 crc32(CRC32 crc,const void *data,size_t size)
{
  const byte *p = data;

  while(size--)
  {
    crc = ((crc >> 8) & 0x00FFFFFF) ^ m_crc32_table[ (crc ^ *p++) & 0xFF ];
  }

  return(crc);
}

What could it possibly be complaining about? Only when investigating the second warning did I realize what the problem was—while I wasn't calculating the CRC over the entire structure, valgrind didn't know that. That explains the first two warnings. The third one deals with this bit of code:

for (i = j = 0 ; i < g_poolnum ; i++)
{
  /* other code */

  if (difftime(Tao,g_pool[i].atime) < c_timeout_gray)
  {
    g_pool[j++] = g_pool[i];
    continue;
  }

  /* rest of loop */
}

g_pool is an array of structures, and I'm using the C89 feature of structure assignment to avoid having to write memcpy(&g_pool[j++], &g_pool[i], sizeof(struct tuple)). But memcpy() (which is what the compiler changes the code to internally) has undefined semantics when the memory blocks overlap, and they do when i == j. This doesn't seem to cause a problem, but who knows?

I also found out that valgrind stops reporting errors after 100,000 are found:

==27967== More than 100000 total errors detected.  I'm not reporting any more.
==27967== Final error counts will be inaccurate.  Go fix your program!
==27967== Rerun with --error-limit=no to disable this cutoff.  Note
==27967== that errors may occur in your program without prior warning from
==27967== Valgrind, because errors are no longer being displayed.

Most of these deal with the child process created to save the state. I don't bother with cleaning up too much since upon calling _exit() all memory is reclaimed anyway, so I'm not terribly concerned about it. But I did lose two hours of testing to this.

Update on Tuesday, October 1616, 2007, 6 hours, 20 minutes and 9 seconds after starting the current test run of the greylist daemon

Bad news—it's still running.

You might think this is good news, but it's not. It means that the debugging conditions have changed the conditions the code runs under, so something very subtle is happening.

I did, however, make one small change to the code, clearing up two of the warnings mentioned above. I would hate to think that making that one small change fixed the program. If it's still running in the morning, then I'll run it again without valgrind and see if it works.

Sigh.

Tuesday, October 16, 2007

Heisenbugs … they're everywhere!

So I ran the greylist daemon for over eight hours under valgrind without it once hanging. I then restarted the server, this time running alone.

A few hours later, it hung.

And just for the record, when I normally attach to the running processing using gdb, it's where I would expect it to be:

(gdb) where
#0  0x008067a2 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2
#1  0x003c2dd1 in recvfrom () from /lib/tls/libc.so.6
#2  0x08049411 in mainloop (sock=0) at src/main.c:88
#3  0x080493a6 in main (argc=1, argv=0xbfe5c084) at src/main.c:68

but when the process hangs:

(gdb) where
#0  0x00dff7a2 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2
#1  0x00955e5e in __lll_mutex_lock_wait () from /lib/tls/libc.so.6
#2  0x008e7e4f in _L_mutex_lock_10231 () from /lib/tls/libc.so.6
#3  0x00000000 in ?? ()

I have no clue as to what's going on (and neither does gdb apparently). Running the program under valgrind obviously changes the environment, enough to mask the condition that causes the bug in the first place.

This is proving to be a very difficult bug to find.


Help! My compiler is leaking!

I fixed the problems that valgrind was complaining about in the greylist daemon (and I had hoped such problems would fix the problem, but alas, it doesn't seem to be the case, but I'm still testing), but the very nature of one of the complaints is interesting in and of itself.

A design pattern I've long used in code is the following:

/*--------------------------------------------
; the following is written to clarify 
; the issue I'm writing about.  This
; is not how I would normally write such 
; code.  It presents a simplified, yet
; realistic bit of code.
;
; And yes, this is the format I use for block
; comments in C.
;------------------------------------------*/

char   buffer[BUFSIZ];
size_t i;
size_t j;

for (i = j = 0 ; i < BUFSIZ ; i++)
{
  if (!isctrl(buffer[i]))
    buffer[j++] = buffer[i];
}

Basically, I'm going through a character array, removing certain elements (in this example, control characters) and doing so in place, to conserve memory consumption. Yes, there are instances where I'm reading and writing the same value to the same location, but in the scheme of things, it's not a bad thing. And, at least for this example, the overhead of trying to avoid unnecessary copying of data overwhelms the amount of time it takes to just do the copy.

So when I was writing the code to clean up the tuple array in the greylist daemon, I naturally wrote it as:

for (i = j = 0 ; i < g_poolnum ; i++)
{
  /* other code */

  if (difftime(Tao,g_pool[i].atime) < c_timeout_gray)
  {
    g_pool[j++] = g_pool[i];
    continue;
  }

  /* rest of loop */
}

It follows a successful pattern I've used plenty of times before. I saw nothing necessarily wrong with it, yet valgrind complained bitterly about this fragment of code. And I was a mildly surprised to see a call to memcpy() when I never explicitly called memcpy().

I just got bit with a leaky abstraction, and a rather insidious one at that.

Pre-ANSI C, I wouldn't have been able to write that code, since back then, C didn't have the concept of structure assignments, and thus, I would have had to explicitly call memcpy():

if (difftime(Tao,g_pool[i].atime) < c_timeout_gray)
{
  memcpy(&g_pool[j++],&g_pool[i],sizeof(struct tuple));
  continue;
}

But one of the advantages of working up the abstraction scale (so to speak) is that you can let the compiler take care of the grunt work for you. I mean, what if struct tuple was the size of an int? The overhead of calling memcpy() would swamp the actual act of copying the data. In fact, if struct tuple was a small multiple of an int in size, it might still not be worth the overhead of calling memcpy(). And the compiler is a better place to push such knowledge, since it can keep track of not only structure sizes, but the overhead of calling a function to copy memory and handle things accordingly.

So ANSI C allowed the compiler to handle structure assignment. And it can do a pretty fine job of it too. For instance, using a recent version of gcc with the compiler options -O3 -fomit-frame-pointer (some heavy duty optimization), it compiled the following bit of code:

struct foo
{
  int f;
};

struct foo A[256];
size_t     i;
size_t     j;
  
for (i = j = 0 ; i < 256 ; i++)
{
  if (A[i].f == 56)
    A[j++] = A[i];
}

to the following bit of x86 code (and frankly, I was surprised at the quality—and it's been translated from the alien AT&T syntax gcc uses to proper Intel syntax):

	xor	edx,edx
	xor	eax,eax
	jmps	.L6

.L4:	inc	eax
	cmp	eax,255
	ja	.L12   

.L6:	cmp	[A + eax*4],56
	jne	.L4
	inc	eax   

	mov	[A + edx*4],56	; A[j].f = 56
	inc	edx		; j++
	cmp	eax,255
	jbe	.L6 
                
.L12:

It didn't even copy the data since the compiler figured out it didn't need to. Even if we increased the size of the structure a bit:

struct foo
{
  size_t f;
  size_t f2;
  char   f3a;
  char   f3b;
  char   f3c;
  char   f3d;
  short  f4a;
  short  f4b;
};

struct foo A[256];
size_t     i;
size_t     j;
  
for (i = j = 0 ; i < 256 ; i++)
{
  if (A[i].f == 56)
    A[j++] = A[i];
}

gcc still has yet to call memcpy():

	push	ebx
	xor	edx,edx
	xor	ebx,ebx
	mov	ecx,255
	jmps	.L18   

.L16:	add	edx,16
	dec	ecx   
	js	.L23  

.L18:	cmp	[A + edx],56
	jne	.L16
     
	mov	[A + ebx],56		; A[j].f   = 56
	mov	eax,[A + 4 + edx]	; A[j].f2 = A[i].f2
	mov	[A + 4 + ebx],eax
	mov	eax,[A + 8 + edx]	; A[j].f3(a-d) = A[i].f3(a-d)
	mov	[A + 8 + ebx],eax
	mov	eax,[A + 12 + edx]	; A[j].f4(a,b) = A[i].f4(a,b)
	mov	[A + 12 + ebx],eax

	add	edx,16
	add	ebx,16
	dec	ecx   
	jns	.L18  

.L23:	pop	ebx

It just copies the 16 bytes of the structure as one assignment (because of constant propagation) and three four-byte moves. It's not until the structure gets significantly large:

struct foo
{
  size_t f;
  char   b1[124];
  size_t s2;
  char   b2[124];
};

struct foo A[256];
size_t     i;
size_t     j;

for (i = j = 0 ; i < 256 ; i++)
{
  if (A[i].f == 56)
    A[j++] = A[i];
}

that the compiler switches to calling memcpy():

	push	edi
	push	esi
	push	ebx
	xor	esi,esi
	mov	edi,offset A
	mov	ebx,255
	jmps	.L40

.L38:	add	esi,256
	dec	ebx
	js	.L45

.L40:	cmp	[A + esi],56
	jne	.L38
	push	ecx	; ???
	push	256
	lea	eax,[A + esi]
	mov	edx,edi
	push	eax
	push	edx
	call	memcpy
	add	edi,256
	add	esp,16
	add	esi,256
	dec	ebx
	jns	.L40

.L45:	pop	ebx
	pop	esi
	pop	edi

(The only anomaly in the code is the push ecx. The register isn't initialized, and memcpy() only takes three parameters, not four. My guess is that this “additional parameter” exists to keep the stack aligned along a cache line and it's this type of detail that compilers exist to keep track of. It's also interesting to note that when compiling for an 80486, gcc never bothers to call memcpy() and instead inlines the operation using REP MOVS.)

By now, you're probably asking yourself, “So? Where's the leaky abstraction?”

Well, the leaky abstraction comes in the call to memcpy(), which happened inherently.

Synopsis

#include <string.h>
void *memcpy(void *s1,void *s2,size_t n);

Description

The memcpy function copies n characters from the object pointed to by s2 into the object pointed to by s1. If copying takes place between objects that overlap, the behavior is undefined.

Returns

The memcpy function returns the value of s1.

The C Standard (emphasis added)

Well, how about that? I'm inadvertantly invoking undefined behavior in the greylist daemon! (actually, I was hoping this was the cause of the problem, but I don't think it is—sigh) Technically speaking, I don't see how there could be a problem when I'm copying a block of memory over itself, except for consuming some extra CPU time. But I would think that a compiler could see I was modifying an array of items, and either include a check to skip the operation if they overlapped completely, or switch to using memmove() (which allows the objects to overlap).

But such is the nature of working with high abstractions. When they leak, they leak!

I suppose I could have realized I was ultimately calling memcpy(), and that memcpy() has undefined semantics when the source and destination overlap, but I also expected the compiler to inline the code to copy the structure (much like gcc did when compiling on an 80486), not actually call memcpy()!

Sheesh.

Wednesday, October 17, 2007

Supreme being, or stinking rich?

“You see, to be quite frank Kevin, the fabric of the universe is far from perfect. It was a bit of a botch job you see. We only had seven days to make it. And that's where this comes in. This is the only map of all the holes. Well why repair them? Why not use 'em to get stinking rich?”

Randall—self-appointed leader of the time bandits

Hmm … stinking rich.

Evil: When I have the map, I will be free, and the world will be different, because I have understanding.

Robert: Uh, understanding of what, Master?

Evil: Digital watches. And soon I shall have understanding of video cassette recorders and car telephones. And when I have understanding of them, I shall have understanding of computers. And when I have understanding of computers, I shall be the Supreme Being!

Hmm … Supreme Being.

After consideration, once I get The Map (link via columbina) I'll go the stinking rich route. The food's better.


Maybe this time I'll get it

I think nailed that heisenbug in the greylist daemon. Given that it somehow ends up in the weeds (as a friend of mine used to say), I decided on a lark to delete all logging from the program.

Okay, it's not as insane as it sounds. The program supports logging to either syslogd or to stdout, selectable at runtime. To support this, I use a function pointer to store which logging routine to use (why I do this is a topic for another time). The functions themselves work very much like printf(), meaning they take a variable number of arguments and a format string describing the type of each argument.

The easiest way to test that particular hypothesis was to rip out that code (only on the production server).

Six hours later, it's still running, which is a very good sign.

I then audited the code, and yes, there were a few type mismatches and one instance of a mismatched number of parameters. Fixed those up, and restarted the greylist daemon.

Hopefully this will fix the problem.

Update a few hours later …

[stupid bugs]

Thursday, October 18, 2007

Everything always works the first time on Star Trek

They always made it look so easy on Star Trek: The Next Generation.

The Enterprise (NCC-1701-D) is facing certain doom by the imminent implosion of a nearby nebula because the Thalaxians stole the warp core because they need it for a new face-lift technology that's a little less than enviromentally sound.

Wesley barges onto the bridge. “Hey guys! What if—”

“Get that kid off the bridge,” says Captain Jean-Luc “I'm a Shakespearian actor, not a ham” Picard, as he does his patented Picard Maneuver.

“But guys,” says Wesley, as he flips Worf onto his back and steps on his throat to prevent being forcibly removed from the bridge, “what if we were to reverse the tachyon field and reroute it through the shield generators to generate an anti-inertial damping field while simultaneously firing a photon torpedo loaded with an anti-matter implosion detonation device?”

“Why is that kid still—”

“And because we've generated an anti-inertial damping field outside the ship,” says Chief Engineer Geordi “Kunta ‘Reading Rainbow’ Kinte” La Forge, interrupting the French British French British (aw, the heck with it) stuffy shirt Captain.

“The force generated by the anti-matter implosion detonation device will push us,” says Lt. “Fully functional, if you know what I mean, and I think you do, wink wink nudge nudge say no more say no more” Data, as he's rapidly calculating something on the computer console in front of him, “into Warp two point seven eight.”

“Which is fast enough to get us out of range of the imminent implosion of a nearby nebula!” says Wesley, still holding down a struggling Worf. Captain stuffy shirt Picard looks momentarily confused as he quickly glances at all three expository spewing characters.

“And if we can place the photon torpedo loaded with the anti-matter implosion detonation device 22,453 kilometers at zero one five mark seven two, then we'll end up right next to the Thalaxian ship.”

“Make is so,” says Picard. “And hurry—we only have one more commercial break before the end of the show.”

And so, in twenty minutes, Wesley, Data and Geordi have managed to execute this complicated technobabblish plan flawlessly. On the first attempt. Based only on a hunch. Of a teenaged geek.

Ah, if only real life were as simple.

But I got the heisenbug nailed.

Latest statistics from the greylist daemon
Start Wed Oct 17 23:48:32 2007
End Thu Oct 18 17:01:55 2007
Running time 17h 13m 23s
IPs 117
Requests 3381
Requests-Cu 3
Tuples 1031
Graylisted 3240
Whitelisted 18
Graylist-Expired 2216
Whitelist-Expired 0

So, what was the fix?

It was a comment from Mark about signal handlers under Unix that lead the way.

Now, on to your bug. I would say 99% it is timing. Furthermore if I were a betting man I would say your bug rests within a signal handler. The only thing you can ever do inside a signal handler is set the value of a volatile sig_atomic_t variable really. Nothing else is safe.

That's pretty much how I wrote the signal handlers:

static volatile sig_atomic_t mf_sigint;
static volatile sig_atomic_t mf_sigquit;
static volatile sig_atomic_t mf_sigterm;
static volatile sig_atomic_t mf_sigpipe;
static volatile sig_atomic_t mf_sigalrm;
static volatile sig_atomic_t mf_sigusr1;
static volatile sig_atomic_t mf_sigusr2;
static volatile sig_atomic_t mf_sighup;

/**********************************************/

void sighandler_sigs(int sig)
{
  switch(sig)
  {
    case SIGINT   : mf_sigint   = 1; break;
    case SIGQUIT  : mf_sigquit  = 1; break;
    case SIGTERM  : mf_sigterm  = 1; break;
    case SIGPIPE  : mf_sigpipe  = 1; break;
    case SIGALRM  : mf_sigalrm  = 1; break;
    case SIGUSR1  : mf_sigusr1  = 1; break;
    case SIGUSR2  : mf_sigusr2  = 1; break;
    case SIGHUP   : mf_sighup   = 1; break;
    default: _exit(EXIT_FAILURE); /* because I'm stupid */
  }
}

/*************************************************/

void check_signals(void)
{
  if (mf_sigalrm)  handle_sigalrm();
  if (mf_sigint)   handle_sigint();
  if (mf_sigquit)  handle_sigquit();
  if (mf_sigterm)  handle_sigterm();
  if (mf_sigpipe)  handle_sigpipe();
  if (mf_sigusr1)  handle_sigusr1();
  if (mf_sigusr2)  handle_sigusr2();
  if (mf_sighup)   handle_sighup();
}

check_signals() is called during the main loop of the program; it's only sighandlers_sigs() that's called in a signal context. The only two signals that get (or rather, got) special treatment are SIGSEGV and SIGCHLD. The handler for SIGSEGV logs that it was called, unblocks any signals and re-executes itself.

The other signal is SIGCHLD. SIGCHLD is sent when a child process ends. It's then up to the parent process to call wait() (or one of its variants) to obtain the return code of the child process. If the parent doesn't do that, the child process becomes a zombie. The SIGCHLD signal handler called waitpid() (which is supposedly “safe” to call from a signal handler) as well as some logging routines. What may be happening (or was happening) is some very subtle race condition. The logging routine does allocate some memory (temporarily). The problem comes in if we're in the middle of allocating some memory when the program receives a SIGCHLD, at which point, we immediately enter the signal handler, which attempts (indirectly, through the logging routines) to allocate memory. But we were already in the memory allocation code when it got interrupted, thus leaving things in an undefined (or inconsistent) state.

I'll expound on what Mark said, and say that once you start dealing with signals, you're dealing with a multi-threaded application, and all the hurt that implies.

I rewrote the SIGCHLD handler to work like the other handlers (signal handler sets a flag, which is checked later from the main execution loop) and well, 17 hours later it's still running, on the virtual server, checkpointing itself every hour.

This only took, what? About a month to find?

But then again, I wasn't facing down the Thalaxians.

Friday, October 19, 2007

“You're programming it wrong.”

This function essentially sums all even integers from 0 to i inclusive. However, this function contains two tail calls, and what's worse as the function recurses those two tail calls are interleaved (in this case, the pattern of that interleaving is simple and easily determined in advance, but there is no reason why that would be the case in general). As far as I can see, this means that it is now impossible to record, or calculate, a full error report in the presence of tail calls in a static amount of stack space. The previous trick of recording a pointer is of little use, since every time tail recursion occurs via a different line of code than the previous call, then a new counter needs to be created pointing to the new tail call location: in the worst case, this will lead to exactly the same number of stack levels being recorded as in the unoptimized tail calling case.

Tail Call Optimization

The lack of a stack trace in tail calls is one reason to dislike them. But I dislike them for an entirely different reason.

Now, just to refresh your memory, a recursive function is a function that calls itself:

fib(i)
  if i = 0 
    return 0
  else 
    if i = 1 
      return 1
    else 
      return fib(i - 1) + fib(i - 2)
    end
  end

result = fib(10);

But recursion is expensive, as it requires aditional stack frames to handle (but it's the stack frames that make debugging easier if it's required). If the last thing a function does is call itself:

mult(a,b)
  if a = 1
    return b
  else
    return(a - 1,b+b)
  end

the compiler can turn this into a loop. And this space optimization (and that's what it is) is called `tail call optimization.” But it has to be of that form, where the last thing the routine does is call itself (and yes, the example mult() function above doesn't work for values of 0 or less, but this is an example).

fib2(i,current,next)
  if i = 0
    return current
  else
    return fib (i - 1,next,current + next)
  end

result = fib2(10,0,1);

But at that point, can you really consider it recursion? If the only way you get the benefit is to construct non-intuitive recursive functions that you can't even get a proper trace out of, isn't calling such an optimization “elegant” a polite fiction? Isn't the compiler there to take care of such details for me? Why should I be forced to write convoluted code to get decent performance? If I want that, I can code in C.

And that's my problem with tail call optimization.

Saturday, October 20, 2007

Some more musings on coroutines, plus a “proof-of-concept”

I spent today playing around with coroutines and how I might go about implementing them. My feeling is that with the upcoming push for multiprocessor systems, using some form of coroutines might make better use of such power, while at the same time being a bit easier to wrap the brain around instead of dealing with actual multithreaded programming.

My “ideal sample program,” which is a pseudo-C like language, looked like:

int main(string argv[])
{
  file input  = file.stdin;
  file output = file.stdout;
  
  switch(argv.items)
  {
    case 3: output = file.open.write(argv[2]);
    case 2: input  = file.open.read(argv[1]);
    default: break;
  }
  
  input => conversion(toupper)
        => strip_html
        => rot(13)
        => conversion(tolower)
        => rot(13)
        => output;
  exit(EXIT_SUCCESS);
}

/********************************************/

coroutine void conversion(char (*conv)(char))
        receive char c;
        send char;
{
  while(receive c)
    send conv(c);
}

/*********************************************/

coroutine void strip_html
        receive char c;
        send char;
{
  char c;
  bool in_tag = false;
  
  while(receive c)
  {
    if (c == '<')
      in_tag = true;
    else if (c == '>')
      in_tag = false;
    else
    {
      if (!in_tag)
        send c;
    }
  }
}

/******************************************/

coroutine void rot(int bias)
        receive char c;
        send char;
{
  while(receive c)
  {
    if (c.isupper)
    {
      c += bias;
      if (c > 'Z') c -= 26;
    }
    else if (c.islower)
    {
      c += bias;
      if (c > 'z') c -= 26;
    }
    
    send c;
  }
}

Why yes, the code in main() is reminiscent of the Unix command line. That's the intent. And on a uniprocessor machine, I suppose the code generated would be such that control would pass from one routine to another via some form of interprocedural goto (but hidden, much like the gotos are hidden in a while loop). And on a multiprocessor (or multicore) machine, you could create cheap threads and pipe the data between each coroutine.

And that's what my first prototype version did. This prototype is about three times longer, and uses pipes to transfer the data among the five threads that were created.

/*----------------------------------------------
; error checking removed to keep this example
; short.  It's already getting a bit silly
; in length, don't you think?
;---------------------------------------------*/

rc = pipe(p1);
rc = pipe(p2);
rc = pipe(p3);
rc = pipe(p4);

/*---------------------------------------------------
; the following is so I can avoid doing single byte
; calls to read() and write(), which will definitely
; destroy any performance gains we might get on a 
; multiprocessor system.  By wrapping these pipes in
; FILE *s, I automagically get buffering.
;
; Also, these structures contain the local data for
; each of the "coroutines" in this program,
; since I can only pass a single pointer to each.
;---------------------------------------------------*/

t1.fpin  = stdin;
t1.fpout = fdopen(p1[1],"w");
t2.fpin  = fdopen(p1[0],"r");
t2.fpout = fdopen(p2[1],"w");
t3.fpin  = fdopen(p2[0],"r");
t3.fpout = fdopen(p3[1],"w");
t4.fpin  = fdopen(p3[0],"r");
t4.fpout = fdopen(p4[1],"w");
t5.fpin  = fdopen(p4[0],"r");
t5.fpout = stdout;

rc = clone(conversion,&m_stack1[1022],FLAGS,&t1);
rc = clone(strip_html,&m_stack2[1022],FLAGS,&t2);
rc = clone(rot,       &m_stack3[1022],FLAGS,&t3);
rc = clone(conversion,&m_stack4[1022],FLAGS,&t4);
rc = clone(rot,       &m_stack5[1022],FLAGS,&t5);

while(1)
{
  child = waitpid(0,&status,0);
  if (child == -1)
  {
    if (errno == ECHILD) break;
    perror("waitpid()");
  }
}

Not only that, but there're plenty of places where things can break, although in my limited testing, things worked with very minimal error checking. I didn't bother to do any testing, this was more or less a “proof-of-concept” type thing.

I then thought of doing a second implemention, this time doing away with the pipes and seeing if I could somehow pass data directly between the “coroutines.” It required a bit of thought, and the solution I cooked up almost works (and I'll get to that in a bit).

The second version looks a bit like the first, only a bit less overhead since I don't have to create all the pipes:

/*-------------------------------------
; two extra threads are required for
; this version.  One to feed the file
; into the chain of coroutines, and one
; to accept the final data for the
; output file.
;--------------------------------------*/

t0.next = (struct parms_common *)&t1;
t1.next = (struct parms_common *)&t2;
t2.next = (struct parms_common *)&t3;
t3.next = (struct parms_common *)&t4;
t4.next = (struct parms_common *)&t5;
t5.next = (struct parms_common *)&t6;
t6.next = (struct parms_common *)&t0;

t0.pid = clone(INTERNA_input,  &m_stack0[1022],FLAGS,&t0);
t1.pid = clone(conversion,     &m_stack1[1022],FLAGS,&t1);
t2.pid = clone(strip_html,     &m_stack2[1022],FLAGS,&t2);
t3.pid = clone(rot,            &m_stack3[1022],FLAGS,&t3);
t4.pid = clone(conversion,     &m_stack4[1022],FLAGS,&t4);
t5.pid = clone(rot,            &m_stack5[1022],FLAGS,&t5);
t6.pid = clone(INTERNAL_output,&m_stack6[1022],FLAGS,&t6);

All the coroutines are linked together, and for the actual implementation, they all pause() (which stops the thread until a signal is received), and upon receiving a signal, process the data given to it (through a fixed location—you'll see in a second) and then signal the “coroutine” next in line before calling pause(). For instance, the conversion “coroutine”:

int conversion(void *arg)
{
  struct parms_conversion *parm = arg;
  int c;

  while(1)
  {
    pause();
    c = parm->c;

    /*--------------------------------------
    ; convert the data, and dump into the
    ; next coroutine's data block, then
    ; signal it that it can process the data.
    ;----------------------------------------*/

    parm->next->c = (*parm->conv)(c);
    kill(parm->next->pid,SIGCONT);

    /*-----------------------------------
    ; if we got an end-of-file marker,
    ; stop this thread.
    ;----------------------------------*/
    if (c == EOF)
      break;
  }
  _exit(EXIT_SUCCESS);
}

And it worked.

Mostly.

I was able to track the problem down to the stip_html() “coroutine”:

int strip_html(void *arg)
{
  struct parms_strip_html *parm = arg;
  int c;
  int in_tag = 0;

  while(1)
  {
    pause();
    c = parm->c;
    if (c == '<') { in_tag = 1; continue; }
    if (c == '>') { in_tag = 0; continue; }
    if (!in_tag)
    {
      parm->next->c = c;
      kill(parm->next->pid,SIGCONT);
    }
    if (c == EOF) break;
  }
  _exit(EXIT_SUCCESS);
}

It doesn't always trigger the next “coroutine” to run, which ultimately causes everything to grind to a halt. While I can hack this to work, it ultimately shows a rather critical failure on this method of implementing coroutines, in that any coroutine that doesn't send all the data it received further down the line will stop the entire chain.

And issues aside, it was about four times the code as the “ideal program.”

If anything, doing this exercise showed me two things. One, it's probably best to use pipes for “coroutines” under Unix. And two, the overhead in using “coroutines” is a bit frightening to do by hand. And it's frightening to think of all the bits that could fail. But is it worth worrying about? In Assembly it's easy to detect if some mathematical operation overflows (in fact, I haven't come across a CPU that doesn't detect overflow), but it's something I don't really concern myself with in C. Heck, in the first “proof-of-concept” I went with using fgetc() and fputc() which simply return EOF when anything bad happens. Sure, it simplifies the code, but it's hard to determine what went wrong when it goes wrong. Which is why I'm concerned: does abstraction scale?

More thoughts (now surfacing after writing all this): are coroutines really all that useful? I can see using them in mod_blog to simplify some code (mainly, formatting of entries) but in general, not much of the code I've written lends itself really to flow by coroutine. Perhaps it's that I don't have that particular tool in my toolchest and I've learned to work around it.

More pondering is required.

Sunday, October 21, 2007

Musings on four dimensional games

While surfing, I came across a mention of 3D chess, and for some reason, that triggered a memory from, oh, twenty-five years ago or so, where I was reading a gaming magazine (for physical, board-type games, not computer games) where they mentioned a board game involving Time Lords and the Fourth Dimension. I remember wanting that game, but a general lack of funds, and more importantly, a general lack of knowledge of where to get the game, left me imagining just how one could play a 2D board game dealing with time and/or the Fourth Dimension.

It was a curious memory indeed, and I decided to see if I could fish some more information out of this wonderful Intarwebs thang we have nowadays. With just that scant remembrance, I was able to locate the game in question. And not only read a review, but the actual rule sheets as well.

Sad to say, I'm glad I didn't get the game way back then. Cool concept, very poor execution. No time element at all, and a very poor concept of the Fourth Dimension as well (each piece can only move one space—optionally, you can move to a “time warp” and spend up to the next three moves to move two physical spaces on the baord—so much for a viable time warp).

But it did get me to thinking some. How could one design a game with time travel as a move? I remember playing a 4D chess variant, using a 4×4×4×4 board, which consisted of a large mat with 16 4×4 boards printed on it. Each column of boards represented a 4×4×4 volume, with four such “spaces” each representing a moment in time. As you moved your pieces (each side had four pieces, and trust me, that was hard enough) you left markers for each square visited. You could capture a piece by landing on any space with a marker, at which point, the trail of markers “past” that point were removed; of course, your piece could then be captured “earlier” in the game, at which point the captured piece captured by the captured piece was returned to the board at the point it was captured … um … does that make any sense?

Anyway, remembering that, I realized that we have these wonderful devices called “computers” that could keep track of all this stuff. Going back to a Time Lord game with actual “time travel,” the computer can keep track of every move, and allow one to move backwards through previous moves. I personally would restrict it such that you can't move a piece into the future (else what's keeping a player from hiding pieces way into future moves?) and you can't have more than one of any piece (so you can't keep moving your Time Lord piece back into the past and have an infinite army of Time Lords). I would also record the game so that afterwards, you can view in chronological time to see all the pieces wink into and out of existence.

It sounds like it would be horribly complicated, and the inner-geek in me would love to play such a game.

Monday, October 22, 2007

Oh yeah … that other place

Least you think I forgot about the other place, I just added a new entry about greylisting there, since it was a request from Smirk.


Friends don't let friends write signal handlers

Mark has a bit more to say about signal handlers:

From
Mark Grosberg <XXXXXXXXXXXXXXXXX>
To
sean@conman.org
Subject
Signal handlers.
Date
Mon, 22 Oct 2007 14:36:05 -0400 (EDT)

You know, now that I think about it even the write() system call is not totally safe in signal handlers. Why? Because lets say the write system call fails. Furthermore lets say that the signal was delivered somewhere in the return path of some other function, like, oh, I dunno, a socket I/O call.

So the socket I/O call has been performed and we are in the midst of unwinding through the various layers of libc and have set errno to some important value (like say HOST-NOT-REACHABLE) and then our signal handler attempts to write … poof our important errno value gets corrupted!

Amusingly from the man page for signal on my system:

Additionally, inside the signal handler it is also considered more safe to make a copy of the global variable errno and restore it before returning from the signal handler.

Too bad if you are in a threaded program “errno” is actually #defined as something like (*__pthreads_get_errno_location()). Hahah! You're so double-XXXXXX with this its not funny. Assuming that getting the errno location is atomic, is loading/storing errno? What if you have some goofy architecture where writes to errno are not atomic and require multiple instructions. That's why sig_atomic_t is so special … it's guaranteed atomic.

The fact that errno is a global variable is a consequence of the C language and it's rather poor support for multiple return values (it can—it's just that you have to pass in additional pointers). At the time, it was the easiest thing that could possibly work (I swear—at times, it feels like if it wasn't in Unix V7, then it doesn't really work that well under modern versions of Unix, like threads), not the best thing that could possibly work (like writing a systems language that supported multiple return values).

And the whole (*__pthreads_get_errno_location()) is telling—the C Standard requires that errno “expands to a modifiable lvalue”—in other words, it could be a pointer to a location which can be changed.

In fact, the C Standard on errno only covers half a page, and P. J. Plauger states in his book The Standard C Library:

If I had to identify one part of the C Standard that is uniformly disliked, I would not have to look far. Nobody likes errno or the machinery that it implies. I can't recall anybody defending this approach to error reporting, not in two dozen or more meetings of X3J11 [The ANSI working committee on standardizing C in the late 80s. —Editor], the committee that developed the C Standard. Several alternatives were proposed over the years. At least one faction favored simply discarding errno. Yet it endures.

The C Standard has even added to the existing machinery. The header <errno.h> is an invention of the committee. We wanted to have every function and data object in the library declared in some standard header. We gave errno its own standard header mostly to ghettoize it. We even added some words in the hope of clarifying a notoriously murky corner of the C language.

A continuing topic among groups working to extend and improve C is how to tame errno. Or how to get rid of it. The fact that no clear answer has emerged to date should tell you something. There are no easy answers when it comes to reporting and handling errors.

It's a rather depressing chapter to read, and P. J. Plauger is right—reporting and handling of errors is difficult reguardless of language.

But errno isn't the only problematic area with signals, so too might be pthreads, making a three-for-one clusterXXXX of your code.

Sigh.

Tuesday, October 23, 2007

Premature optimization

“We should forget about small efficiencies, say about 97% of the time. Premature optimization is the root of all evil.”

Knuth, Literate Programming, 1992, p28.

Nobody wants to argue with Knuth—it is the equivalent of arguing against the second law of thermodynamics. However, the problem here is that too often people misunderstand what Knuth was getting at.

Mature Optimization

I often feel as if the industry has gone off into collective insanity because of Knuth's quote, that concerns for programming efficiency are brushed aside because, well, optimization is eeeeeeeeeevil, people! Eeeeeeevil! (And if you really want to go down this rabbit hole, writing code is a form of premature optimization, because it's already been written. Even figuring out the problem is a form of premature optimization since someone already solved it.)

But the article points out that Knuth has been misquoted. Or rather, selectively quoted. The full quote from Knuth's book Literate Programming:

The improvement in speed from Example 2 to Example 2a is only about 12%, and many people would pronounce that insignificant. The conventional wisdom shared by many of today's software engineers calls for ignoring efficiency in the small; but I believe this is simply an overreaction to the abuses they see being practiced by penny-wise-and-pound-foolish programmers, who can't debug or maintain their “optimized” programs. In established engineering disciplines a 12% improvement, easily obtained, is never considered marginal; and I believe the same viewpoint should prevail in software engineering. Of course I wouldn't bother making such optimizations on a one-shot job, but when it's a question of preparing quality programs, I don't want to restrict myself to tools that deny me such efficiencies.

There is no doubt that the grail of efficiency leads to abuse. Programmers waste enormous amounts of time thinking about, or worrying about, the speed of noncritical parts of their programs, and these attempts at efficiency actually have a strong negative impact when debugging and maintenance are considered. We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil.

Yet we should not pass up our opportunities in that critical 3%. A good programmmer will not be lulled into complacency by such reasoning, he will be wise to look carefully at the critical code, but only after that code has been identified. It is often a mistake to make a priori judgments about what parts of a program are really critical, since the universal experience of programmers who have been using measurement tools has been that their intuitive guesses fail.

Knuth, Literate Programming, 1992, p28.

Another article to read about this: The Fallacy of Premature Optimization.


Friends don't let friends code C++

As if the errno fiasco in C wasn't bad enough, not only does C++ inherit that mess, but it comes barreling down the road with a mess of more problems.

Sheesh.

Glad I'm not forced to use C++.

Wednesday, October 24, 2007

144 points of failure

I'm not even sure where to begin with this.

A customer is having a problem with duplicate emails being sent about a month after being initially sent, and it's causing the recipients to freak out (since they can't be bothered to check the date and see it's either a duplicate or a very late email message).

Our problem is obtaining the information we need to troubleshoot this problem. Our customer has no idea what “email headers” are (but then again, our customer has no idea what “a program” is or how she even checks her email) and doesn't want to bother the recipients with such details.

The real problem?

The sheer number of participants in exchanging an email between two parties. Between the two, in this case, are at least four operating systems (running on the customer's computer, our computer, the recipient's email server, and the recipient's computer), six networks (customer's local network, their ISP, our network, the network of the recipient's email server, the recipient's ISP, and the recipient's local network) across an unknown number of routers and at least six programs (customer's email client, incoming and outgoing mail daemons on our server, incoming mail daemon on recipient's server, the mailbox daemon on the recipient's email server, and the recipient's email client), any one of those could cause a minor problem that causes duplicate emails to be sent (and I'll spare you those details).

It's amazing that this crazy patchwork of servers, networks and software works at all, but boy, when it breaks, it breaks in very odd ways. I'm sure that the problem is understandable once we figure out what went wrong, but how to determine what went wrong? Especially after the fact?

Our log files don't go back that far, and what we do have is 10G worth (and due to how sendmail logs emails, an individual email at minimum generates three lines of logging information, and good luck in trying to piece all that together).

I think what I'm grousing about is my inability to fully troubleshoot the issue. The participants aren't necessarily technically inclined (which makes it difficult to get help from them, or even real solid information), and it involves more than just us. And somehow, it's our fault.

Oops. Gotta go. Yet another email issue to troubleshoot.

Now, where did I put my gun?


Thoughts on optimizing a greylist daemon

Speaking of optimization, I thought it might be fun to profile the greylist daemon. It's not difficult—just recompile the program with the appropriate compiler option and run it.

Now, when I wrote the greylist daemon, I did gave thought to how I was going to search through the vast amount of information, and wrote the code with that in mind (oooh, premature optimizations? Or was that a mature optimization?). I was also curious as to any hotspots in the code, as I tend to max out at 130 requests per second on my development server.

The results were a bit surprising:

Each sample counts as 0.01 seconds.
% time cumulative seconds self seconds calls self Ts/call total Ts/calls name
% time cumulative seconds self seconds calls self Ts/call total Ts/calls name
50.00 0.01 0.01 661477 0.00 0.00 tuple_cmp_ift
50.00 0.02 0.01 1 10.00 10.00 whitelist_dump_stream
0.00 0.02 0.00 140892 0.00 0.00 edomain_cmp
0.00 0.02 0.00 108648 0.00 0.00 crc32
0.00 0.02 0.00 95853 0.00 0.00 edomain_search
0.00 0.02 0.00 28270 0.00 0.00 StreamEOF
0.00 0.02 0.00 27439 0.00 0.00 report_stderr
0.00 0.02 0.00 27273 0.00 0.00 ipv4
0.00 0.02 0.00 27165 0.00 0.00 check_signals
0.00 0.02 0.00 27162 0.00 0.00 send_packet
0.00 0.02 0.00 27155 0.00 0.00 ip_match
0.00 0.02 0.00 27155 0.00 0.00 send_reply
0.00 0.02 0.00 27155 0.00 0.00 type_graylist
0.00 0.02 0.00 25458 0.00 0.00 tuple_search
0.00 0.02 0.00 24692 0.00 0.00 tuple_add
0.00 0.02 0.00 24692 0.00 0.00 tuple_allocate

The big surprise was that the execution time was split between two functions, tuple_cmp_ift() (which compares two tuples) and whitelist_dump_stream(), and the amusing bit is the disparity of the number of calls between the two, 661,477 calls to the former vs. the one call to the latter.

But in this case, the one call to whitelist_dump_stream() was made when the program ended (all it does is write out the tuples that have been whitelisted). Remove that from the program, and we pretty much have our hotspot—tuple_cmp_ift().

The other surprise is that there weren't any real surprises. The test data consists of 27,155 tuples with some duplicates, and you can see the various checks were called that many times. The only reason edomain_search() was called as many times as it was is that there are four lists that are checked 24,000 times each. crc32 is called twice for each packet (yes, that's intentional) so divide that by four (request and response) and it fits.

The code is pretty much even except for tuple_cmp_ift(), which is our obvious hotspot.

int tuple_cmp_ift(const void *left,const void *right)
{
  const struct tuple *l = left;
  const struct tuple *r = right;
  int                 rc;

  ddt(left   != NULL);          /* similar to assert() */
  ddt(right  != NULL);          /* but logs to syslogd */
  ddt(l->pad == 0xDECAFBAD); /* compiled out of profiled */
  ddt(r->pad == 0xDECAFBAD); /* code */

  /*-------------------------------
  ; sizeof(l->ip) is 16 bytes, enough
  ; space to hold an IPv6 address; not 
  ; that we use IPv6 currently, but planning
  ; for the future.
  ;------------------------------------------*/

  if ((rc = memcmp(l->ip,r->ip,sizeof(l->ip))) != 0) return(rc);

  if (l->fromsize < r->fromsize)
    return(-1);
  else if (l->fromsize > r->fromsize)
    return(1);

  if ((rc = memcmp(l->from,r->from,l->fromsize)) != 0) return(rc);

  if (l->tosize < r->tosize)
    return(-1);
  else if (l->tosize > r->tosize)
    return(1);

  rc = memcmp(l->to,r->to,l->tosize);
  return(rc);
}

Now, before I spend any time trying to optimize this bit of code, I thought I'd rerun the program without it. I changed tuple_search() (which calls tuple_cmp_ift()) to simply return “not found,” and I removed the call to whitelist_dump_stream(). The results were even more amusing:

Each sample counts as 0.01 seconds.
no time accumulated
% time cumulative seconds self seconds calls self Ts/call total Ts/calls name
% time cumulative seconds self seconds calls self Ts/call total Ts/calls name
0.00 0.00 0.00 140892 0.00 0.00 edomain_cmp
0.00 0.00 0.00 108668 0.00 0.00 crc32
0.00 0.00 0.00 95853 0.00 0.00 edomain_search
0.00 0.00 0.00 27438 0.00 0.00 report_stderr
0.00 0.00 0.00 27273 0.00 0.00 ipv4
0.00 0.00 0.00 27169 0.00 0.00 check_signals
0.00 0.00 0.00 27167 0.00 0.00 send_packet
0.00 0.00 0.00 27155 0.00 0.00 ip_match
0.00 0.00 0.00 27155 0.00 0.00 send_reply
0.00 0.00 0.00 27155 0.00 0.00 type_graylist
0.00 0.00 0.00 25458 0.00 0.00 tuple_add
0.00 0.00 0.00 25458 0.00 0.00 tuple_allocate
0.00 0.00 0.00 25458 0.00 0.00 tuple_search
0.00 0.00 0.00 3577 0.00 0.00 StreamEOF

Yeah, a lot of called functions, but not enough accumulated time to even survive rounding up.

I'm begining to think that the 130 requests per second limit I'm seeing isn't a function of the code, but of the network stack. Given this result, I doubt I'll bother optimizing tuple_cmp_ift() any time soon, which seems to re-enforce the whole “premature optimization is eeeeevil” thought, but in reality, I wrote the code around a few optimizations (namely, well considered data structures) in the beginning and didn't need to optimize it later.

Thursday, October 25, 2007

Ah, if only I had three cubic acres of coinage …

I'm such the Uncle Scrooge fan that I found this model of his money bin very cool! (link via spin the cat—thanks Jeff!)

Update a few minutes later …

So you're telling me that a duck who has 3 cubic acres of liquid assets and a XXXXXXX moon made of gold isn't the richest fictional character ever created?

Via Flutterby, Financial fan fiction from Forbes

Heh.

Friday, October 26, 2007

Some news on a greylist daemon implementation

I received some good news from Smirk—I can release the greylist daemon as open source. Now all that remains is to clean up the code, find a good name, and write a lot of documentation, pretty much in that order.

Monday, October 29, 2007

“His brain is gone!”

Of all the episodes of Star Trek: The Original Series, of course the only one to make it to the stage is “Spock's Brain” (link via Mike Sterling).

No, really!


Notes on stress testing a greylist daemon

I spent the weekend cleaning up the code to the greylist daemon, in preparation to releasing it. Good thing too, because I've found lots of little details, a missed call to free() here, the wrong constant used there (it didn't matter before the cleanup, afterwards, with some stuff changed, it did), and not updating some statistical information correctly.

Little details like that.

The only big change was the ability to add and remove tuples using the master control program. A nice side effect of that effort, you can now see how a tuple will be handled by the greylist daemon.

The other change is the way I handle stress testing. As a side issue about a parallel quicksort implementation, it was pointed out that the data I collected was bogus, and that I should be handling more requests than I am.

I got to thinking, and it may be that my current stress testing isn't stressful enough.

So I wrote a new stress test. This is basically two programs. The first reads through a list of tuples and generates all the packets, but saves them to a file. The second program maps this file into memory and then sends each packet, one after the other, to the greylist daemon.

My, what a difference.

The initial test was on an old 120MHz machine. The previous stress test capped out at 77 requests per second. The new stress test capped out at 381 requests per second without a dropped packet (another test, this time the stress test program didn't bother waiting for a reply, managed to send 1700 packets a second—the greylist daemon could only handle 385 per second, and obviously dropped a bunch of packets).

Not bad for a 120MHz machine.


It sounds more like a trip through hell to me …

This one is for Gregory, who likes to travel via motocycle: Angola by Motocycle (link via Flutterby).

Tuesday, October 30, 2007

More thoughts on optimizing a greylist daemon

I ran the updated stress test on a faster (2.6GHz machine) and managed to get some impressive results.

There were three different ways I ran the test. One option had the stress program send a request and wait for a reply. This was by far the slowest of the tests, but the most reliable (in terms of actually processing every request) with the greylist daemon handling between 4,000 to 6,300 tuples per second. Another option has a separate process waiting for the replies and that goes faster, between 11,000 and 17,000 tuples per second, but drops a ton of requests (on the order of 70%). The last option doesn't even bother with replies. This does both the best and the worst—30,000 tuples per second, but it drops something like 90%.

So, the program can easily handle about 5,000 requests per second on a nice server, which is probably way more than most SMTP servers can handle (and it's much nicer than the 130/second I thought it could handle).

I profiled the program again, and this time, got actual results I could use:

Each sample counts as 0.01 seconds.
% time cumulative seconds self seconds calls self Ts/call total Ts/calls name
% time cumulative seconds self seconds calls self Ts/call total Ts/calls name
21.24 0.48 0.48 2260060 0.00 0.00 crc32
14.38 0.81 0.33 443203 0.00 0.00 tuple_search
11.51 1.07 0.26 565012 0.00 0.00 ip_match
8.85 1.27 0.20 565012 0.00 0.00 type_graylist
7.97 1.45 0.18 1 0.18 2.20 mainloop
6.64 1.60 0.15 565015 0.00 0.00 send_packet
4.87 1.71 0.11 7648182 0.00 0.00 tuple_cmp_ift
4.87 1.82 0.11 565012 0.00 0.00 graylist_sanitize_req
3.98 1.91 0.09 1761756 0.00 0.00 edomain_search
3.54 1.99 0.08 2637054 0.00 0.00 edomain_cmp
3.10 2.06 0.07 421359 0.00 0.00 tuple_add
2.21 2.11 0.05 565012 0.00 0.00 send_reply
2.21 2.16 0.05 1 0.05 0.05 whitelist_dump_stream
0.89 2.18 0.02 565127 0.00 0.00 ipv4

Again, nothing terribly surprising here, except for the code gcc generated for the crc32() function (two lines of C code, one of which is while(size--)), but I used the default compiler settings; if it really bothers me, I can up the compiler settings and see what I get.


There's no place like 127.0.0.1

If you are threatening to hack someone's computer to their face, you should at least know better than to attack anyone who claims their IP address is 127.0.0.1 (link via tryss).

Wednesday, October 31, 2007

“Every eye was a stranger eye. Every nose was a weirder nose. Every mouth smiled hideously in some new way.”

[Boo!]

“It was a dark and stormy night; the rain fell in torrents—except at occasional intervals, when it was checked by a violent guest of wind which swept up the streets …”

And so begins Edward George Bulwer-Lytton's Paul Clifford, as wretched a novel as existed, and it described tonight fairly well as I took The Kids trick-or-treating. The wind was so violent that it constantly inverted my umbrella and in the end, I gave up on using it.

And The Kids scored some 11 pounds of candy this year.

Unfortunately for me, they're not leaving for their Father's tomorrow

Sigh.

Thursday, November 01, 2007

Fifteen hundred words a day apparently is a problem.

Today is November 1st.

And that can mean only one thing: the start of National Novel Writing Month.

And like many years gone past I will yet again attempt to write a novel.

Last year (as well as years before) I really didn't have a solid idea going into the month on what to write, so I never got very far. Part of that problem is that I have a hard time writing fiction. While I don't lack for ideas, I do however, lack the discipline to see these ideas through.

I said as much to Spring, and she suggested an idea I can get behind: to write a non-fiction book about a fictitious subject.

It's certainly a better idea than writing 50,000 fictitious words.

We'll see how far I get this year.

Friday, November 02, 2007

Notes on releasing an open source project

I spent the day cleaning up the build process for the greylist daemon as a few people have asked for it. I think the worst aspect of this is writing the gobs of documentation for the program. What I have now is enough for someone familiar with installing non-autoconf packages to get it up and running, but there's still plenty more to write.

Sigh.

Saturday, November 03, 2007

Yup, fifteen hundred words a day is about fourteen hundred a day too many

I'm begining to think that writing 50,000 fictitious words is probably the only way I'll ever complete a novel during National Novel Writing Month.

Spring and I went to a local meetup of fellow Nonowrimoers in Palm Beach County, which clarified my thoughts about Nanowrimo—basically, I'm not up to the task. I just don't have the headspace for fictional writing, nor even non-fictional writing about a fictional subject.

Part of that is lack of discipline; on remaining focused on finishing a task when I've become bored of it, or I find it too difficult and wander off on some other project. Another part is the aformentioned headspace. It's not that I lack ideas—I have plenty of ideas. I just lack the ability to write more than a few hundred words about any of them.

And it certainly didn't help matters that the atmosphere of the meetup was not conducive to writing—what with having to block out the loud conversations about Harry Potter and classroom hijinks.

Sunday, November 04, 2007

A 64bit version of the greylist daemon

I met with Mark (and JeffK) for dinner tonight as payment for helping to get the greylist daemon running on his system. I was glad to do it, if only to keep me honest in my code; Mark's system is a 64-bit version of OpenBSD on a non-Intel platform, and it took a few days (since I didn't have direct access to his systems and we were communicating via email) to get it mostly working (there are apparently a few details I still need to iron out).

Monday, November 05, 2007

And I thought I was being extravagant for using 20 megabytes for the greylist daemon

As if the problems I'm having getting the greylist daemon 64-bit clean and less Linux-centric weren't bad enough, today I find that the Sendmail client just stopped working. I checked the logs, and sure enough, the milter library is bitching up a storm:

Oct 31 17:32:08 XXXX smgl: Greylist Daemon: thread_create() failed: 12, try again
Oct 31 17:32:44 XXXX last message repeated 5 times
Oct 31 17:33:13 XXXX last message repeated 10 times
Oct 31 17:33:17 XXXX smgl: Greylist Daemon, mi_rd_cmd: read returned -1: Connection reset by peer
Oct 31 17:33:17 XXXX smgl: Greylist Daemon, mi_rd_cmd: read returned -1: Connection reset by peer
Oct 31 17:33:17 XXXX smgl: Greylist Daemon: thread_create() failed: 12, try again
Oct 31 17:33:50 XXXX last message repeated 13 times
Oct 31 17:34:52 XXXX last message repeated 28 times
Oct 31 17:35:54 XXXX last message repeated 34 times
Oct 31 17:37:02 XXXX last message repeated 21 times
Oct 31 17:38:05 XXXX last message repeated 7 times
Oct 31 17:39:11 XXXX last message repeated 16 times
Oct 31 17:40:20 XXXX last message repeated 7 times
Oct 31 17:41:31 XXXX last message repeated 8 times
Oct 31 17:41:50 XXXX smgl: Greylist Daemon: thread_create() failed: 12, try again
Nov  1 12:22:53 XXXX smgl: Address: 127.0.0.1:0
Nov  2 19:25:21 XXXX smgl: Greylist Daemon: mi_stop=1
Nov  2 19:27:56 XXXX smc: Address: 0.0.0.0:0

Okay. That mi_stop=1 doesn't look good; let me see what I can find out about that:

On Tue, 27 Jul 2004, Matt Selsky wrote:

Jul 27 09:12:20 clover mimedefang[22489]: [ID 649295 mail.info] MIMEDefang-2.44: mi_stop=1

This is normal.

Regards,

David.

[Mimedefang] mi_stop=1 message in syslog

Lovely! Not only is it normal, but the only reference I found was dated 2004!

There was nothing at all about mi_rd_cmd returning -1, but I did find the following about the thread_create() failed: 12:

On Thu, 28 Oct 2004, Stephane Lentz wrote:

PS: a folk running Linux reported a similar problem but he's not runing RH. On Mandrake/SuSE I've never seen it. How much traffic do you process ? Which hardware ? Try to get some recommendations on system tuning from RH since you're paying $$$$ .

Here's some free advice: On RHEL3, type “ulimit -s”:

$ ulimit -s
10240

So each thread wants 10MB of stack space. That can chew up your RAM pretty quickly. I recommend editing the MIMEDefang startup script and putting:

ulimit -s 2048

just before mimedefang (not the multiplexor!) is invoked.

Right now, the sample red hat script does it only if you have more than 100 slaves, but it should really do it unconditionally.

Regards,

David.

[Mimedefang] thread_create errors

Sweet Jesus! No wonder the Sendmail client sucks up memory like there's no tomorrow! Sheesh!


This doesn't appear to be a reprint of an Onion article—perhaps that's why I find this so frightening

The 23-year-old, who said she had left school without a maths GCSE, said: “On one of my cards it said I had to find temperatures lower than -8. The numbers I uncovered were -6 and -7 so I thought I had won, and so did the woman in the shop. But when she scanned the card the machine said I hadn't.

“I phoned Camelot and they fobbed me off with some story that -6 is higher—not lower—than -8 but I'm not having it.”

Via theferrett, ‘Cool Cash’ card confusion

No wonder the Week ly World News folded—it couldn't compete with the real news.


I wonder what grade this would get at the Harvard Business School?

And speaking of lotteries tax breaks for the smart

In 1992, a group of Australian investors—led by math whiz Stephan Mandel decided they could literally buy the $27 million jackpot in the Virginia state lottery. Racing against the clock, they bought 5.6 million of a total 7.1 million possible combinations.

The Australians walked away with the only winning ticket—and $27 million.

Big lotto jackpot not what it seems

Actually, I'm surprised this hasn't happened more often (or maybe it does and is underreported). In our own little lovely state of Florida, our little state lottery has a 22,957,480:1 odds of winning, so it would seem that somebody would try it, once the pot has grown to, maybe, three times that amount, which does happen, to make it profitable, if maybe a bit logistically daunting.

I would also expect that the Australians probably did a bit better than the $27 million, because lesser combinations (like 5 out of 6) also pay out.

Tuesday, November 06, 2007

A shot to the arm

[Back many years ago I wrote a humor column for the FAU newspaper (which doesn't exist as I knew it, but that's a story for another time), in which half the time I took a small incident in my life but put a highly fictional spin to it. Perhaps that's what I really need to do—get back to that gonzo mindset and relive my early childhood 20s as a semi-fictional writer. Or something like that.]

[Oh, and I forgot—you have been warned.]

Concerned for my health, Bunny thought it prudent that I get a flu shot, and she knows me well enough to know that I wouldn't willingly go get one on my own. I hate shots. I hate needles. It's probably the only thing that kept me from becoming a heroine junkie.

Well, that, and the relative lack of non-sequential US $100 bills.

But mostly it was the needles.

I was touched by her concern, but felt that dragging me kicking and screaming into the clinic by my ears was uncalled for; her .357 would have certainly made the point clear and been less painful [But as she's quick to point out to the writer, she doesn't have a concealed weapons permit. Yet. —Editor]. I will say that to the nurses' credit, they didn't bat an eye as we came in screaming; they just shoved forms our way and turned to the only other customer there, an older, chain smoking gentleman complaining about an upper respiratory problem, and chided him to put out those cigarettes.

I refused to fill out the forms.

Bunny refused to let go my ear, a bit harder this time.

After a few minutes of this painful stalemate, I compromised. I filled out the form, but left the Social Security field blank. I'm such the rebel.

I don't remember much past that though. I think I tossed the forms back at the nurses, then made a dash towards the door. I either ran into the older chain-smoking gentleman with an upper respiratory problem who was giving one of the nurses a piece of his mind with the most graphic of language, or Bunny body tackled me. In any case, the world quickly turned dark as I experienced sudden deceleration trauma.

I awoke to a piercing pain in my right arm. The nurse was grinning as she shoved a bit harder. I countered with a piercing shriek. She countered with shoving the syringe in hard. I countered by blacking out.

“There,” said Bunny when I finally awoke. I found myself lying on the floor, looking up. “That wasn't so bad, was it?”

Wednesday, November 07, 2007

Named

Since Smirk helped to fund the development of the greylist daemon he had a hand in naming the actual product, and we decided upon X-Grey. The site will be up in a few days, and then it will be officially released to the public.

Woot.

Thursday, November 08, 2007

Notes on an Emergency Room Conversation

“Clear the way!” I said, rushing into the Emergency room with The Younger slung over my shoulder. “Medic! Cortisone stat!” I plopped The Younger down on the counter in front of the on-duty nurse.

“Who are you, and what's wrong with him?”

“You!” I pointed at some random medical personnel who happened to be walking by, “500ml of saline solution, stat! This boy is in real need of medical attention. Take a look,” I said, pointing to The Younger's hand. The nurse at the front desk picked up The Younger's hand and looked at it.

“I don't see anything wrong.”

“What are you, blind? The other hand! Where's that saline solution? Where's the cortisone?”

The nurse picked up the other hand and peer closely. “I still don't see anything.” I pointed to a spot on The Younger's hand. “What is that? A mosquito bite?”

That,” I said, “is a puncture wound from a staple.”

The nurse blinked at me. Loudly. The whole room was filled with the sound of the nurse's blinking. “A staple wound.”

“My God nurse! How can you stand there like that? This boy needs medical attention! Stat! Where is that cortisone?” I started looking around the room for anyone to order around.

“How old is he?”

“Eleven,” I said.

“Twelve,” said The Younger, with an exasperated tone to his voice as if he's been constantly correcting adults in his age for two months.

“Twelve,” I said. “You!” I pointed to another random medic. “Warm up the CAT scanner!”

“He attends middle school, right?”

“Have you yet to take your Hippocratic Oath? This boy needs immediate medical attention.”

“Yes,” said The Younger.

“The only thing he needs is maybe a tetanus shot—”

“You! Tetanus shot! Stat!” The random medic I ordered just looked at me rather funny and continued on her way.

“—and if he's in middle school, then he's already had his tetanus shot. It's part of his DTP shot he needed to get into middle school.” The nurse looked rather pissed.

“…”

“Anything else I can do for you or the kid?”

“…”

“Thank you. Have a nice day.”

Friday, November 09, 2007

I hate it when real work intrudes at work

I had planned for a nice quiet day at The Office, one where I could work on getting the website for X-Gray but nooooooooooooooooo! Smirk had other ideas for me, like actual work work, which involved moving several websites from a shared environment (running under Insipid) to individual virtual servers (each running Badminton).

Nothing like having to reverse engineer the setup from one <shudder> control panel to another <shudder> control panel.

Sigh.

Monday, November 12, 2007

This metablogging entry brought to you by the letter B. And by the number 13.

It was a quiet weekend (more like comatoast since I didn't bother to post anything) and even today was rather quiet (well, other than moving websites). I started to write something about string concatenation in Ruby and that if one method is frowned upon, why does it even exist, but I just wasn't in the mood to even bother.

Heck, I havn't been in the mood to post in the past few days.

In other news, I got another testimonial about X-Grey:

From
kelly@XXXXXXX
To
Sean Conner <sean@conman.org>
Subject
Re: Greylist daemon …
Date
Mon, 12 Nov 2007 14:06:12 -0500 (EST)

So far, NOTHING (spamwise). I don't know what I'm going to do with all this free time not deleting spam! (pause 1.5 hours for work interruption)

heh … Thanks …

plus some other feedback (some small bugs, omissions from the installation documentation). So far, everybody who's used X-Grey has been happy with it.


What next? That the Mona Lisa is really a self portrait?

ROME, Italy (AP)—It's a new Da Vinci code, but this time it could be for real.

An Italian musician and computer technician claims to have uncovered musical notes encoded in Leonardo Da Vinci's “Last Supper,” raising the possibility that the Renaissance genius might have left behind a somber composition to accompany the scene depicted in the 15th-century wall painting.

Via Instapundit, Italian musician uncovers hidden music in Da Vinci's ‘Last Supper’

For Bunny, who likes both music and The Da Vinci Code.

Tuesday, November 13, 2007

X-Grey

I'll be the first to admit it's not pretty, and it's rather concise, but in order to get this thing out of the door, X-Grey is officially released.

Wednesday, November 14, 2007

Notes on a possible way to store tuples in a greylist implementation

I was checking some other greylist implementations when I came across an implementation that only stores a 32-bit hash instead of the full tuple. The idea sounded intriguing, and since I'm already calculating a 32-bit CRC as part of my protocol, I thought it might be interesting to see just how effective it might be.

Out of 499,846 unique tuples checked, only 28 had duplicate CRCs. I think I could live with that; I could then store 32× the number of tuples in the same amount of memory. Of course, I lose the ability to see the actual tuples, but for a huge ISP or webhosting company trying to deal with an insane amount of email, that is certainly a viable option (hint, hint—Rob, you listening?)

Thursday, November 15, 2007

I've blogged for so long, I'm beginning to forget what I've blogged about

Heh. Here I was, getting ready to post about The IDE Divide when, searching for past entries about my dislike of IDEs, I found out I already did (three years ago!).

This time, I definitely identified with being a language maven, but I can certainly understand the lure of being a tool maven. When programming, it's not uncommon for me to have half a dozen (or more) terms open, editing code, viewing a few header files, a few man pages open, and a command line sitting ready for compiling. I'm not much on syntax highlighting, but automatic code completion would definitly be nice, or perhaps a form of running commentary on the code.

Friday, November 16, 2007

It seems that the Event Horizon for Computer History is somewhere around six minutes

So I'm reading Reddit and come across an article about the increasing bloat in Microsoft applications. Nothing terribly new there, but this bit:

The Stone Age

Back in 1999, when I was working as an advisor to Intel's Desktop Architecture Labs (DAL), I remember how thrilled we all were to get our hands of Windows 2000 and Office 2000. Finally, a version of the Windows/Office stack that could leverage all of the desktop horsepower we were building in to the next generation Pentium 4 platform …

First-off, let me characterize the state-of-the-art at the time. The Pentium 4 CPU was about to be unveiled and the standard configuration in our test labs was a single-CPU system with 128MB of RDRAM and an IDE hard disk. While a joke by today's standards, this was considered a true power-user configuration suitable for heavy number- crunching or even lightweight engineering workstation applications.

What Intel Giveth, Microsoft Taketh Away

has me going nuclear.

Stone Age? In 1999?

It's 1988 and I'm given an account on the university VAX, sharing the CPU with 50 other people on a system that might have had 4MB of RAM and a few hundred megabytes of disk space (we were only allowed five minutes of CPU time per day, which was enough for regular usage, although a friend of mine did manage to blow through that limit regularly by playing a version of Space Invaders he wrote for it).

It's 1984, and for my birthday (and Christmas of 1983—given that my birthday is two weeks after) I received a Color Computer 2, running at a heart stopping 889kHz with a whopping 16KB of memory and a highly advanced means of block storage—the cassette recorder (which recorded data at a breathtaking speed of 1500 baud).

Methinks the author of the above article is in desperate need of a clue-by four.

Stone age my XXX.

Saturday, November 17, 2007

Apparently Snopes didn't have anything to say on this topic

I just got the following from Bunny via email, who got it from someone else via email, who got it from someone else via email …

[Iconic markings on a gas gauge]

I didn't know this! Did you?

I have been driving for over forty years. One would think I would have noticed the little secret on my dashboard that was staring me right in the face the whole time. I didn't and I bet you probably haven't either.

Quick question, which side of your car is your gas tank on? If you are anything like me, you probably can't remember right away. My solution is to uncomfortably stick my head out the window, strain my neck and look. If you don't do this in your own car you definitely have done it in a borrowed or rental car.

Well, ladies and gentlemen, I'm going to share with you my little secret so you will no longer look like Ace Ventura on your way to the gas station or put your neck at risk of discomfort or injury.

If you look at your gas guage, you will see a small icon of a gas pump. The handle of the gas pump will extend out on either the left or right side of the pump. If your tank is on the left, the handle will be on the left. If your tank is on the right, the handle will be on the right (see photo above). It is that simple!

I don't know how you feel right now but when I found out this morning I felt cheated!

Why don't the dealers share such important information with car buyers? I don't understand why this isn't in the driver's manual? I don't get why any mechanic I have ever been too or know has even thought of mentioning this to me? The only possible explanation can be that all these people probably don't even know!

Go out and share the world's best kept auto secret with your friends as this information is way too important to be kept secret.

So I went out to Lake Lumina (as my car is known—and it's a long story why it's known as Lake Lumina, which is for another time) and checked. Lo' and behold—it was false.

But! It could still work. Even though the gas tank on Lake Lumina is on the left side, and the gas pump printed on my gas gauge with the handle on the right side, the gas pump is oriented the correct way were I to drive up to one.

So it could be that the gas pump is drawn to show the orientation of the pump as you drive up to it. I'll have to check more dash boards to be sure though.

Sunday, November 18, 2007

Nine Inch Noëls

The thought of singing Head Like A Hole in the style of the Chairman of the Board has always been amusing to me, but now I've found something that's just as amusing, yet actually exists—Nine Inch Noëls, a medly of classic Christmas songs sung with Nine Inch Nails lyrics (link via Joey deVilla).

And yes, it is just as funny as it is wrong.

Monday, November 19, 2007

Burning down the house

I'm feeling much better today.

Back on Friday I first felt the inklings of a cold inching its way into my system, and I began a schedule of heavy vitamin-C and a sea of fluids, followed by heavy sleep, and that seems to have done the trick.

But it wasn't all chicken soup and tissues. On Sunday, groggy from having just gotten up (around 7:00 pm), I went to the kitchen to make some tea and soup. I turned on the wrong burner (easy enough to do) and almost burned down Casa New Jersey when a stove cover (these thin metal lids that cover stove burners when not in use) caught fire. Fortunately, Wlofie caught it in time.


Notes on the Great Stove Top Fire Incident of 2007

On second thought, maybe I'm not 100% yet. In rereading the previous entry, I realized I should have put a gonzonian fictional spin on the Great Stove Top Fire Incident of 2007.

Ah well … I'm feeling too lazy still recovering from my near death cold experience.

Tuesday, November 20, 2007

Little green bunnies

“Alba”, the green fluorescent bunny, is an albino rabbit. This means that, since she has no skin pigment, under ordinary environmental conditions she is completely white with pink eyes. Alba is not green all the time. She only glows when illuminated with the correct light. When (and only when) illuminated with blue light (maximum excitation at 488 nm), she glows with a bright green light (maximum emission at 509 nm). She was created with EGFP, an enhanced version (i.e., a synthetic mutation) of the original wild-type green fluorescent gene found in the jellyfish Aequorea Victoria. EGFP gives about two orders of magnitude greater fluorescence in mammalian cells (including human cells) than the original jellyfish gene.

Alba, the fluorescent bunny

Ah, leave it to the French to concoct a gazillion-word manifesto on the artistic and social æsthetics of mutant green bunnies in French culture (and I don't mean a yogurt based sauce either).

And oh, by the way, the mutant green bunny actually exists.


Testing a reverse captcha

Back when you could sign up to get email notifications of updates around here, I noticed some spammers were attempting to abuse the script, and after playing around with it, I decided to scrap that feature, but later mused on using a reverse captcha to keep spammers at bay.

But while I dont' have comments, I do invite comments on another website I control. And that form is now getting spammed (and like my former Obligatory Email Notification, the only one who sees anything is me).

Heavily.

And when they're not hawking 3″ mortgage extensions, I get incomprehensible stuff like:

Name
embohette
Email
gorgiovgit@list.ru
Comment
<a href="http://salihome.info/show/index.html">Three hip-hop artists have key parts in American Gangster.</a><br> <a href="http://oscines.cn/myspace-layout/index.html">Andre 3000 takes a turn with Charlize Theron in Battle in Seattle.</a><br> <a href="http://myspace-layout.tripod.com/">Robert De Niro and Al Pacino reunite next year in the crime drama…</a><br> <a href="http://rigolu.cn/sex-portal/main.html">MORE big screen… </a>
Submit
Panic

So I decided to put my “reverse captcha” theory to the test. I added a non-displaying <TEXTAREA> to the form, and if it's changed in any way, I ignore the submission. I'm curious to see how long it takes the spammers to adapt, if any bother.

Monday, November 26, 2007

A little lapse in posting

Wow, a week has gone by without a post.

What happened?

Um … a bloggers strike … yea … that's it. The local Blogger Chapter #34 went on strike. You know how it is …


The Secret Temple (that's not so secret anymore)

Here, 100ft down and hidden from public view, lies an astonishing secret one that has drawn comparisons with the fabled city of Atlantis and has been dubbed “the Eighth Wonder of the World” by the Italian government.

For weaving their way underneath the hillside are nine ornate temples, on five levels, whose scale and opulence take the breath away.

Constructed like a three-dimensional book, narrating the history of humanity, they are linked by hundreds of metres of richly decorated tunnels and occupy almost 300,000 cubic feet—Big Ben is 15,000 cubic feet.

Indeed, the Italian government was not even aware of their existence until a few years ago.

But the “Temples of Damanhur” are not the great legacy of some long-lost civilisation, they are the work of a 57-year-old former insurance broker from northern Italy who, inspired by a childhood vision, began digging into the rock.

Via Instapundit, Eighth wonder of the world? The stunning temples secretly carved out below ground by “paranormal” eccentric

It's amazing what Oberto Airaudi has been able to accomplish, unseen, in thirty years of work.


Musings on high volume email servers and X-Grey, the greylist daemon

On Saturday, I bumped into Rob at a “After Thanksgiving Party” and we discussed the use of X-Grey at Negiyo, at least, those parts of Negiyo email that Rob helps to manage.

The code, as is, won't work with their setup. First problem, the sheer volume of email—something like 100,000 connections per second. These are fed through two load balancers and farmed out to about 100 servers, so each server is responsible for 10,000 connections per second. While I suspect X-Grey can handle 10,000 connections per second, the major problem are the load balancers—there's just no guarantee that the load balancers will be consistent on which machine they send the connection to.

For instance, we have some machine, on IP address 10.20.30.40 sending an email from alice@example.net to bob@negiyo.com. The load balancer will send that to server A, which doesn't find the tuple [10.20.30.40 , alice@example.net , bob@negiyo.com], stores it for later reference, and sends back “try again later.” Later, the machine at 10.20.30.40 tries sending the email again, only this time, the load balancer sends the connection to server B, which doesn't find the tuple, stores it, and sends back “try again later.” Lather, rinse, repeat until the sender gives up, or the load balancer manages to send the traffic to a machine that actually has the tuple stored.

There's just no way of knowing which server the load balancer will send the traffic to. So, we point all the servers to a single greylist server, which now has to handle 100,000 requests per second. Okay, so assuming X-Grey can handle that load (it's a real beefy box on a fat pipe), and given that we store greylisted tuples for six hours … carry the one … 2,160,000,000 tuples.

Blink.

Blink.

Okay, now that I'm actually doing the math instead of sitting around in a comfortable chair listening to Rob while chowing down on turkey and stuffing, I find it rather difficult to believe that Negiyo is getting around 8½ billion emails per day—even a billion per day is stretching my credibility. The worst we get at The Company is 8 per second, with an average hovering around 1.4 (or 122,540 per day, which I calculated twice, using two different statistics that are recorded). More believable is 100,000 per hour (or even up to 1,000,000 per hour, which is 11 emails per second).

I'll have to get back with Rob on this …


Guerrillas clandestinely time their movement in Paris clock

Four members of an underground “cultural guerrilla” movement known as the Untergunther, whose purpose is to restore France's cultural heritage, were cleared on Friday of breaking into the 18th-century monument in a plot worthy of Dan Brown or Umberto Eco.

For a year from September 2005, under the nose of the Panthéon's unsuspecting security officials, a group of intrepid "illegal restorers" set up a secret workshop and lounge in a cavity under the building's famous dome. Under the supervision of group member Jean-Baptiste Viot, a professional clockmaker, they pieced apart and repaired the antique clock that had been left to rust in the building since the 1960s. Only when their clandestine revamp of the elaborate timepiece had been completed did they reveal themselves.

Via tryss, Undercover restorers fix Paris landmark's clock

And speaking of clandestine construction, what's up with the Europeans?

Tuesday, November 27, 2007

Cognitive dissonance

Intellectually, I know that The Holidays are not over yet, and that if anything, they're just now picking up steam, but to me, it feels like it's already over. Normally, this would be a Good Thing™ but the cognitive dissonance I'm experiencing is annoying.

Here it is, just shy of December, and it's still hot. Okay, it's not August “so hot the asphalt is boiling” hot, but it's still warm enough for natives to still be wearing tee-shirts and shorts. There are precious little decorations littering the landscape, and I've yet to see any palm trees smothered in lights.

It just doesn't feel like The Holidays (granted, when I first moved down here it didn't feel like The Holidays then either, what with trees still having leaves—green leaves at that, and no snow, and it wasn't freezing during the day). And I have to wonder why I feel so cheated.

Perhaps because it's still hot.

I think we need to get Al Gore down here—oh wait, gotta go … Bunny wants to shop for Christmas trees …


Mind the announcer

It's too bad that Emma Clark is no longer the voice of the London Underground (link via Flutterby). Some of her announcements are rather amusing.

Wednesday, November 28, 2007

Stupid multithreaded benchmarks

Dan Lyke ran a stupid benchmark—just incrementing a variable to a billion, one just flat out, and one between some pthreads locking primitives.

I wanted to see what stupid results I would get if I used spin locks. First, the relevant bit of code (used nasm to compile it under a 2.6GHz dual-core Pentium running Linux 2.6):

		bits	32
		global	t1
		global	t2

		section	.data
gv		dd	0
glock		dd	0

		section	.text

		align	16
t1:		mov	eax,[gv]
		inc	eax
		mov	[gv],eax
		cmp	eax,1000000000
		jl	t1

		; ret

	; the following implements _exit()
	; for the multithreaded version

		xor	ebx,ebx
		mov	eax,252
		int	$80
		mov	eax,1
		int	$80
		hlt

		align	16
t2:		mov	al,1
t2.wait:	xchg	al,[glock]
		or	al,al
		jne	t2.wait
t2.here:	mov	eax,[gv]
		inc	eax
		mov	[gv],eax
		mov	byte [glock],0
		cmp	eax,1000000000
		jl	t2
	
		;ret
	
		xor	ebx,ebx
		mov	eax,252
		int	$80
		mov	eax,1
		int	$80
		hlt

Straightforward implementations here. t1() is the straight through counting routine, while t2() is the one with the spin lock. Running single threaded yielded these results:

Counting, single threaded
routine time to execute
t1() 2.454s
t2() 39.752s

While I expected the spin lock to be faster than the pthread locking, I wasn't expecting it to be this slow. But maybe, just maybe, I'll get some of that speed back by running dual threads. At the very least, it should be a bit faster than single core, right?

Right?

Bueller? Bueller?

Counting, dual-threaded
routine time to execute
t1() 0m10.334s
t2() 2m31.307s

Um …

Wow.

I didn't expect spinlocks to be so expensive.

Ouch.

Thursday, November 29, 2007

More stupid multithreaded benchmarks

The other interesting thing to think about: at what point do we beat the same algorithm in C, and how hard would it be to parallelise the algorithm in C with pthreads

Use those extra cores and beat C today! (Parallel Haskell redux)

Since I'm doing stupid benchmarks anyway, why not this? I didn't use pthreads though—I haven't used that particular API in about a decade, and even then, I wasn't thrilled with it.

Nope. Instead I used a Linux specific call—clone(), wrote a small function to wait for all the threads that were created, and basically spent about five minutes making a parallelized C-version of the Fibonacci sequence. Granted, I had to do the parallelization explicitly, but it wasn't that difficult to do.

The hard part was finding a quad-core box to test this on. Fortunately, I know we have one at The Company (shhh—don't tell Smirk) and that's where I spent most of my time on this—locating our single quad-core machine I could test this on.

But find it I did. And yes, the program does run faster the more cores that are thrown at it, but it's not a linear speed up:

A Parallelized Fibonacci Sequence calculation program
# cores Runtime
1 0m31.468s
2 0m19.521s
4 0m17.234s

It's interesting that it appears to be bottoming out rather quickly (and these are average times over a few runs).

Friday, November 30, 2007

Obsessing over stupid benchmarks (and you thought my obsessing over a greylist daemon was bad … )

I'm still obsessing over stupid benchmarks. This time, I was curious about the overhead of calling functions and system calls, to simulate a typical locking scenario, like:

int gv;

void t(void)
{
  while(gv < 1000000000)
  {
    lock();
    gv++;
    unlock();
  }
}

So, I wrote some test code:

int gv

void null(void)
{
}

void t1(void)
{
  while(gc < 1000000000)
  {
    null();
    gv++;
    null();
  }
}

void t2(void)
{
  pid_t me;

  me = getpid();
  while(gc < 1000000000)
  {
    kill(me,0);
    gv++;
    kill(me,0);
  }
}

The first test is pretty simple—it just tests the function call overhead, and that particular piece of code takes 9 seconds (give or take a few tenths of a second) to run. But let me explain about the second test, and therein lies the interesting bit of this tale.

I wanted to test the system call overhead, and thus, I needed a system call that did very little. I found this bit in the kill() manpage:

If sig is 0, then no signal is sent, but error checking is still performed.

That's about as close to a null system call as I could find. No real bad side effects, and I don't particularly care about the return code (since this is just measuring overhead). So I ran that bit of code. Fifteen minutes later it finished.

Fifteen minutes.

Either system calls are slow, or that particular system call does a vast amount of nothing. Curious, I delved into that part of the kernel source (I'm running all this under Linux, by the way) when I came across this bit of kernel code:

asmlinkage long sys_getpid(void)
{
	return current->tgid;
}

Now, I knew that getpid() was a system call, but I didn't realize it was a system call. What I mean by that is, even though it's documented in section 2 of the manual (usually reserved for system calls), it may not actually call into the kernel. For instance, alarm() is documented in section 2, but it's a library call that eventually calls other system calls. And I thought that getpid() was a library call that just returned a value (the current process ID) stored in userspace (which makes sense to me—it's not like it changes or anything as the process runs). I didn't expect it to be an actual system call.

Well then.

And it's about as low overhead of a system call as you can get.

So I rewrote t2():

void t2(void)
{
  while(gc < 1000000000)
  {
    getpid();
    gv++;
    getpid();
  }
}

And the runtime dropped to 17 seconds.

Okay, much better. Not quite twice the function call overhead. But what the heck was kill() doing that warranted fifteen minutes? I checked the Linux source code and it didn't appear to be that much. What the heck was going on?

So what's the actual code to getpid()? Was it perhaps making the system call once and storing the result? Time to check the code to getpid(). Easiest way to do that was to statically compile the test program, and disassemble it (using objdump):

0804e380 <__getpid>:
 804e380:       b8 14 00 00 00          mov    $0x14,%eax
 804e385:       cd 80                   int    $0x80
 804e387:       c3                      ret

Okay. Not much to it. What if I make the system call directly then? And here, I resorted to assembly (since the inline assembly directives for gcc make no sense to me whatsoever):

t41:	mov	eax,20
	int	$80    
	mov	eax,[gv]
	inc	eax
	mov	[gv],eax
	mov	eax,20
	int	$80
	mov	eax,[gv]
	cmp	eax,1000000000
	jl	t41
	ret

(oh, the reason the code looks a bit different? objdump uses AT&T syntax, while nasm uses Intel syntax)

It was a bit surprising to find myself waiting for 11 minutes for this bit of code to run.

Okay, that's more on par with using the system call kill(), but that doesn't explain why my version took 66 times longer. Perhaps it's a CPU pipeline issue? Perhaps it is faster to call a function that invokes a system call than it is to inline the actual system call. So I'll called the function getpid():

	extern	__getpid

t42:	call	__getpid
	inc	dword [gv]
	call	__getpid
	cmp	dword [gv],1000000000
	jl	t42
	ret

Back to 17 seconds. Okay, what if I supply my own wrapper function around the getpid() system call?

t43:            call    getpid
                inc     dword [gv]
                call    getpid
                cmp     dword [gv],1000000000
                jl      t43
                ret

getpid:         mov     eax,20
                int     $80
                ret

And just to make sure, check with objdump:

080484b0 <getpid>:
 80484b0:       b8 14 00 00 00          mov    $0x14,%eax
 80484b5:       cd 80                   int    $0x80
 80484b7:       c3                      ret

 ...

0804e420 <__getpid>:
 804e420:       b8 14 00 00 00          mov    $0x14,%eax
 804e425:       cd 80                   int    $0x80
 804e427:       c3                      ret

So, other than the memory location of the routine (and the name, but the name isn't part of the executable) they're the same. So why does my version of the getpid() function take 11 minutes to run? Something odd is going on somewhere.

I then wrote a version of getpid() that caches the return value from the first call (and this time, I made it callable by C functions):

		global	my_getpid

my_getpid:	mov	eax,[pid]
		or	eax,eax
		jz	.10
		ret
.10		mov	eax,20
		int	$80
		mov	[pid],eax
		ret

Two tests, one calling this routine from C, another test calling this routine from another assembly routine. And both take around 10 seconds to run, which is just a shade slower than calling a null routine.

But calling __getpid() (the system supplied C library routine that calls the system call) is faster than calling getpid() (the function I wrote to call the system call), even though they're identical functions.

Is there something else going on that I'm not aware of?

Weird …

Saturday, Debtember 01, 2007

“We have met the enemy, and it is us.”

You are at a party, and you get bored. You say “This isn't doing it for me anymore. I'd rather be someplace else. I'd rather be home asleep. The people I wanted to talk to aren't here.” Whatever. The party fails to meet some threshold of interest. And then a really remarkable thing happens: You don't leave. You make a decision “I don't like this.” If you were in a bookstore and you said “I'm done,” you'd walk out. If you were in a coffee shop and said “This is boring,” you'd walk out.

You're sitting at a party, you decide “I don't like this; I don't want to be here.” And then you don't leave. That kind of social stickiness is what Bion is talking about.

And then, another really remarkable thing happens. Twenty minutes later, one person stands up and gets their coat, and what happens? Suddenly everyone is getting their coats on, all at the same time. Which means that everyone had decided that the party was not for them, and no one had done anything about it, until finally this triggering event let the air out of the group, and everyone kind of felt okay about leaving.

This effect is so steady it's sometimes called the paradox of groups.

A Group Is Its Own Worst Enemy

Spring and Wlofie were supposed to join some friends canoeing in the swamp (that's what we have here in Florida, swamps). But then the person who proposed the canoeing trip in the first place had a family emergency and couldn't make it. That caused another member to drop out. Then a third piped in, saying he couldn't make it because he was still recovering from a cold, and that his wife was now sick. Wlofie dropped out because his wrist is acting up again (Carpal tunnel syndrome) and because he wasn't going, Spring dropped out.

Pretty much in the span of a few hours, the entire trip just fell apart.

I find it interesting how that works.


I'm surprised the studio didn't explode

Because I have a few readers who might find this interesting: Phil Donahue (a notorious left-wing liberal) interviewing Ayn Rand (a notorious right-wing conservative) (link via Right on the Left Coast).

Sunday, Debtember 02, 2007

Multiple system calls

I finally found the answer to little conundrum. But first, a bit of a recap—the code for __getpid (the function that acually does the system call) that I presented:

0804e380 <__getpid>:
 804e380:       b8 14 00 00 00          mov    $0x14,%eax
 804e385:       cd 80                   int    $0x80
 804e387:       c3                      ret

That was generated from the output from objdump, and in order to get that, I had to compile the program using gcc -g -static -o t1 t1.o t1a.o, but note the -static bit there. Normally, such routines are part of a shared library that aren't included in the final executable, but by adding -static when compiling, the routines in the standard libraries are included in the final result. And had I run the statically compiled version, I would have seen that the code that calls the system supplied __getpid() would have taken 11 minutes to run.

What bit of code was I actually testing?

(gdb) disassemble __getpid
Dump of assembler code for function getpid:
0x00820730 <getpid+0>:  mov    %gs:0x4c,%edx
0x00820737 <getpid+7>:  test   %edx,%edx
0x00820739 <getpid+9>:  mov    %edx,%eax
0x0082073b <getpid+11>: jle    0x82073e <getpid+14>
0x0082073d <getpid+13>: ret    
0x0082073e <getpid+14>: jne    0x820752 <getpid+34>
0x00820740 <getpid+16>: mov    %gs:0x48,%eax
0x00820746 <getpid+22>: test   %eax,%eax
0x00820748 <getpid+24>: nop    
0x00820749 <getpid+25>: lea    0x0(%esi),%esi
0x00820750 <getpid+32>: jne    0x82073d <getpid+13>
0x00820752 <getpid+34>: mov    $0x14,%eax
0x00820757 <getpid+39>: call   *%gs:0x10
0x0082075e <getpid+46>: test   %edx,%edx
0x00820760 <getpid+48>: jne    0x82073d <getpid+13>
0x00820762 <getpid+50>: mov    %eax,%gs:0x48
0x00820768 <getpid+56>: ret    
0x00820769 <getpid+57>: nop    
0x0082076a <getpid+58>: nop    
0x0082076b <getpid+59>: nop    
0x0082076c <getpid+60>: nop    
0x0082076d <getpid+61>: nop    
0x0082076e <getpid+62>: nop    
0x0082076f <getpid+63>: nop    
End of assembler dump.

Ah! That makes more sense then!

It's basically checking to see if the getpid() system call has been made, and if not, call it once, then cache the value for later calls to this routine. You also won't notice an int $80 here, but that's because the shared library version of __getpid() uses a different method of making a system call than the traditional int $80, although the older method is still supported, which is why I suspect the static version of the system libraries use int $80 to make system calls—to support older systems that might not support the newer system call mechanism.


As long as they refrain from installing WiFi, it should be okay

For Mark, who may or may not find this horrifying (he used to work on car diagnostic software, so he's had more than enough exposure to automobile based networks): BMW testdriving IP as the underlying protocol for car computers (link via Instapundit).

Monday, Debtember 03, 2007

RedJournal

By now it's probably all over the place that SixApart sold LiveJournal to a Russian company and there's been a lot of commentary over the move, both apprehensive and negative.

I don't really have a stake in this horse, seeing how I run my own site and everything, but I do have to wonder—would SUP (owners of LiveJournal and supporter of Putin) censor posts (or even accounts) that said stuff like “Putin is a lying, corrupt scumbag politician who should be thrown into jail, much like he's done to his opponents.”? Not terribly far-fetched if you ask me.

Granted, it may be the Russian government wanted control of the Russian LiveJournal, but sometimes, it pays to be prudent.

Tuesday, Debtember 04, 2007

Easily amused

Wow!

Just wow—crayon physics.

Wednesday, Debtember 05, 2007

Need more info

I want to help. I really really really really want to help.

No, really! I do.

But when you report an issue as:

XXXX@XXXXXXXXXXXXXXXXXX.com is having some outgoing email issues. She doesn't rec. any error msgs. The email leaves her inbox and arrives at its destination anywhere from 3hrs to 8hrs later. Can we make sure this domain is not having issues? Maybe check the logs and be sure that the delay is not on our end?

I can't help you very much. Sure, I have the sending address. What about the recipient(s) address(es)? Which addresses are having problems? Sendmail logs around three lines per email, with the sender address on one log line and the recipient address on another log line, which makes it rather difficult to correlate senders with receivers.

Give me too much information. It's easier for me to discard what I don't need than to have to ask for more information.

Just so you know.

Also, EMAIL IS NOT INSTANT MESSAGING! It got through, didn't it? So what's the problem? Oh, you want instant results? Use IM. Or even that archaic of technologies, the phone.

Sorry about that. Just needed to vent a bit.

Thursday, Debtember 06, 2007

Because out of context, this is really funny

[Nuclear Missile Combat Crew • Death Wears Bunny Slippers]

(Oh, you want some context? Fine (link via Flutterby))


On the plus side, you won't get idiots driving on the shoulders …

While the traffic is bad down here in Lower Sheol during this time of year, the roads themselves are decent, and there is no chance what-so-ever of plunging to your death if you drive off the road (link via Yet Another Really Great Blog).

Friday, Debtember 07, 2007

Talk about making money at niche markets

For some reason, I was struck by either the product, or the business plan—three very interesting online stores:

SmartFlix

For those of you who are into DIY, a website where you can rent thousands of How-To DVDs.

Heavy Ink

This is right up Jeff's alley—a place to buy comic books (all 20% off) with free shipping. As the owner of the site says:

Yeah, we lose big money on the person who orders one comic book.

… but the value proposition is so simple and compelling, that we get tons of customers, who soon start buying enough stuff that it's, on average, worthwhile.

an email to Instapundit

CatGenie

We already get flushable cat litter, but this … wow! We won't even have to do that anymore.

Monday, Debtember 10, 2007

This time, it really was broken

[Bad hub!  No token for you!]

Well, that was pleasant.

I got up this morning afternoon, went to check my email only to find myself logged out. Hmm, I thought. I wonder if there was a network issue? I went to another terminal window, and saw that I was logged out of linus, which isn't across the Internet, but just across the desk from the machine I was using. Now that's odd, I thought. What the heck is going on?

Hey! Who turned off the hub?

Yes, I use a hub. A 12 port 10base-T with AUI and 10base-2 port hub. I picked them up a few years ago, back when I was actively using older systems that didn't support the newer 10base-T Ethernet standard. I'm still using it because of a motto I live by: “if it ain't broke, don't fix it!”

So I reached behind the hub and flipped the switch.

Nothing.

I tried flipping the switch multiple times.

Each time, nothing happened.

I tried saying “xyzzy.”

Nothing happened.

I tried saying “plugh.”

A hollow voice said “plugh,” but the hub still didn't work.

“Well XXXX,” I said.

One major expedition to clear the desk later, I had the hub pulled out and open. The fuse was still good. Power was getting to the power supply. But power was not getting to the rest of the system. The power supply was shot.

“Well XXXX,” I said.

Getting a replacement wasn't hard. “Smirk,” I said on the phone, “do you have a spare switch or hub lying around?”

“Yes, I have this five port 10/100base-T switch. Will that work?”

“Perfect! I'll be over to pick it up.”

No, that was the easy part.

The hard part was getting rid of the 10base-2 portion of my network (remember: “if it ain't broke, don't fix it.” And until today, it weren't broke). The good part: linus' Ethernet card had a 10base-T port. The bad part: janet's (the firewall system) Ethernet card to my part of the network didn't.

“Well XXXX,” I said.

I scoured various boxes for an AUI-10base-T transceiver. Now, AUI-10base-2 transceivers are rare; you can still dig them up, but they're rare. An AUI-10base-T transceiver? Pretty much extinct. I've only seen two of them in my twenty years in this industry, but hey, you never know—I could have one buried somewhere.

Only I didn't.

“Well XXXX,” I said.

I was going to have to swap out a network card in janet. My old webserver, tower had a usable network card with a 10base-T connector. Pull that out. Shut down all the machines on my part of the network, pull janet out from underneath the pile of computers that sit on it. Swap cards. Then realize I have to recompile the Linux kernel on janet (which is a 486, but in the interests of keeping it out of a landfill, I'm using it for a firewall) to support the new card.

“Well XXXX,” I said.

Half an hour later, I got the new kernel working on janet and my part of the network is back up.

Just in time to hit The Melting Pot to celebrate The Older's birthday.


It's interesting to note that in searching for my hub, I found them for sale for anywhere between $20 and “if you have to ask, you can't afford it” (although several places had them listed for between $170-$220). It also seems worth it to fix the darned thing (actually, I have two such hubs, both have blown power supplies) and sell them.

Tuesday, Debtember 11, 2007

“He's dead, Jim.”

[Of course he's dead!  He's wearing a red shirt!]

A rather unfortunate inflatable Santa I passed on the way to work this afternoon.


It's either this or war …

It seems like everytime we meet with G, our Cisco consultant, he keeps trying to push IPv6 on us, saying we have to test it out.

Now I see why he's always pushing it (link via flutterby).


I felt that this was one of the few memes from what's left of LiveJournal after the Ruskies took over that was worthy enough to not only do, but to actually make a post about it. Fancy that.

[Ow!  My hand is cramped!]
Corsair2's journal King Duncan's journal

Wednesday, Debtember 12, 2007

While the Internet appears to deal well with censorship, it seems to fall a bit flat when it comes to other crimes

Well, hmm, that's odd, I thought, they were there yesterday.

I clicked on the links in the email that I'd sent, and sure enough, all of them showed 404: File Not Found errors. “Now that's damn odd,” I thought.

I went back and repeated the Google search. The same comporomised servers came up. I clicked on the links in Google and found myself redirected to the virus droppers.

I clicked on the links in the email and found myself staring at a 404 File Not Found error.

I clicked on the links in Google and found myself at a virus dropper.

A light bulb went on. “Aha!” I thought. “I bet these redirectors hide themselves! If you visit one of these pages from Google, it'll redirect you; but if not, it won't!”

Via Spring, Polyamory and crime on the Internet

There are three things that would make the Internet a better place. Two are pretty easy, and the third is “pie-in-the-sky” wishful thinking, but anyway …

  1. Isolate Russia from the Internet.
  2. Isolate China from the Internet.
  3. Wipe Windows from the Internet (this is the “pie-in-the-sky” wishful thinking bit).

And while the first two options appear to be rather drastic in nature, they probably won't help as much as the third option (and really, if the third does happen, then the first two probably won't have to be done at all).

Thursday, Debtember 13, 2007

Is separation of logic, display and language even possible?

I was just given a new project from Smirk, with one hard requirement (other than the specification of what the program is supposed to do)—it has to be in PHP (primarily because a) it's a web-based application and b) because it's interfacing to a bunch of other web-based applications written in PHP).

There is a chance down the road that this new project will be released as open source (much like X-Grey), and in order to gain traction as an open source PHP web-based application, it needs to support MySQL, although for our own use, we need to support PostgreSQL, which is nice, since then right out of the box, it'll support two popular database engines.

The only other sticky problem is i18n. I mean, other than character set issues, I want to make it easy to translate the software into other languages, which means keeping most of the text separated from the actual code. And while this is possible with PHP (with lots of self-discipline on the part of the programmer), I would also like a way to separate the language from the layout mechanics.

In other words, I would like to have the program logic, display logic and language independent (as much as possible) from each other, so that it's easy to translate to another langauge, and it's possible to change the look and feel of the program (to match an existing website).

Tall order, and I'm not even sure of the best way to go about handing this. I've seen how some other PHP web-based applications handle it (such as osCommerce and SugarCRM) and to say it's an ugly hack is an understatement.

Friday, Debtember 14, 2007

Stupid GCC Compiler Tricks

Years ago I implemented my own language, and in the process of writing that, I seriously abused the C pre-processor to give me a form of template-based programming (templates are now part of the C++ standard), and while using the template wasn't that bad:

void _MKFUNCTION(T_PREFIX,_matrix)(void)
{
  char *s;
  
  s = get_token(fpin,whitespace);
  string_push(s);
  _MKFUNCTION(T_PREFIX,_matrixq)();
}

But you had to be very careful how you included the templates stuff, or it would most definitely blow up in your face.

But this—implementing a “read-evaluate-print-loop” in C, for C—is sheer genius. Or sheer insanity. I'm not sure which.

Saturday, Debtember 15, 2007

Position wanted: toady

Are you tired of your hum drum routine? Want to meet new people? Get exersice? Learn to obey?

Hot up and comming supervillain, Mannar the Mind Melter, is now accepting oaths of fealty! Yes, now you finally have a chance to enter the exiting and fast paced world of amature/professional henching. Mannar the Mind Melter is looking for young, attractive, intelligent go getters, to serve his whims and follow him around in search of the next great caper!

You'll have a chance to learn valuable new skills, such as scowling and do-gooders, fist shaking, villainous monolouging, working as a team, and serving the glorious leader!

So come on, knaves, near-do-wells, rascals and raggamuffins, your future is waiting now!

To apply, please send a photo, and a declaration of fealty to Mannar the Mind Melter, as well as a short papragraph about yourself and what skills you can offer the Glorious Melter of Minds, via the provided e-mail.

Mannar the Mind Melter
Tyranny, Today!

• it's NOT ok to contact this poster with services or other commercial interests

PostingID: 501909929

Via Craigslist Curmudgeon, Support Local Villainy!

Five years ago I wondered about hiring scientists for secret projects in underground lairs and how one goes about such staffing. Well, it seems that all an aspiring supervillian, like Mannar the Mind Melter, needs to do is advertise in the help wanted section (or in these modern days, on Craigslist).

• it's NOT ok to contact this poster for employment opportunities in secret underground lairs.

Sunday, Debtember 16, 2007

Gives a whole new meaning to the word “automagical” …

To
Albus Dumbledore, Headmaster
From
Coxrid, IT director, Hogwarts School of Witchcraft and Wizardry
Re
My resignation

Headmaster:

I regret that I must resign my position, effective two weeks ago, at least. It is simply impossible under these conditions to create a modern, integrated, flexible IT architecture aligned with the school's educational mission and objectives.

Deployment of the OC-3 fiber backbone met insuperable difficulties, as you know, when the cabling crew was attacked repeatedly by Dementors. Cabling staff rarely are effervescent people in the best of times, and having their life force sucked through their faces by cloaked, shadowy horrors as they lay paralyzed in icy terror is a serious de-motivator.

The trials of the Hogwarts IT director

Ah, I'm so glad I don't have that job.

Monday, Debtember 17, 2007

“You're kidding, right? That's not seriously the error message, right? Bloody PHP programmers … ”

“Sean,” said Smirk, “there's a trouble ticket in the system I want you to look at.”

“Okay,” I said.

“There's a problem with the port of SugarCRM.” We needed SugarCRM, but needed a version that uses PostgreSQL, not MySQL. It took some effort, but we found a PostgreSQL-based version of SugarCRM.

And there seems to be a problem with it.

I check the ticket.

Appears to be a porting error.

Warning: pg_query() [function.pg-query]: Query failed: ERROR: syntax error at or near "contact_name_owner" LINE 1: ... ' contact_na... ^ in XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXinclude/database/pgsqlManager.php on line 136 Error retrieving Lead list: Query Failed:( SELECT meetings.id , meetings.name, meetings.status, ' ' AS contact_name , ' ' AS contact_id , ' ' contact_name_owner , ' ' contact_name_mod , meetings.date_modified , jt1.user_name AS assigned_user_name , jt1.created_by AS assigned_user_name_owner , 'Users' AS assigned_user_name_mod, ' ' filename , meetings.assigned_user_id , 'meetings' AS panel_name FROM meetings LEFT JOIN users AS jt1 ON jt1.id= meetings.assigned_user_id AND jt1.deleted=0 AND jt1.deleted=0 where ( meetings.parent_id= 'd3e15dc6-9525-d1b8-63fb-474f614635fa' AND meetings.parent_type='Leads' AND meetings.deleted=0 AND (meetings.status='Held' OR meetings.status='Not Held')) AND meetings.deleted=0 ) UNION ALL ( SELECT tasks.id , tasks.name, tasks.status , COALESCE(contacts.first_name,'') || ' ' || COALESCE(contacts.last_name,'') AS contact_name , tasks.contact_id , contacts.assigned_user_id AS contact_name_owner , 'Contacts' AS contact_name_mod, tasks.date_modified , jt1.user_name AS assigned_user_name , jt1.created_by AS assigned_user_name_owner , 'Users' AS assigned_user_name_mod, ' ' filename , tasks.assigned_user_id , 'tasks' AS panel_name FROM tasks LEFT JOIN contacts AS contacts ON contacts.id= tasks.contact_id AND contacts.deleted=0 AND contacts.deleted=0 LEFT JOIN users AS jt1 ON jt1.id= tasks.assigned_user_id AND jt1.deleted=0 AND jt1.deleted=0 where ( tasks.parent_id= 'd3e15dc6-9525-d1b8-63fb-474f614635fa' AND tasks.parent_type='Leads' AND tasks.deleted=0 AND (tasks.status='Completed' OR tasks.status='Deferred')) AND tasks.deleted=0 ) UNION ALL ( SELECT calls.id , calls.name, calls.status, ' ' AS contact_name , ' ' AS contact_id , ' ' contact_name_owner , ' ' contact_name_mod , calls.date_modified , jt1.user_name AS assigned_user_name , jt1.created_by AS assigned_user_name_owner , 'Users' AS assigned_user_name_mod, ' ' filename , calls.assigned_user_id , 'calls' AS panel_name FROM calls LEFT JOIN users AS jt1 ON jt1.id= calls.assigned_user_id AND jt1.deleted=0 AND jt1.deleted=0 where ( calls.parent_id= 'd3e15dc6-9525-d1b8-63fb-474f614635fa' AND calls.parent_type='Leads' AND calls.deleted=0 AND (calls.status='Held' OR calls.status='Not Held')) AND calls.deleted=0 ) UNION ALL ( SELECT notes.id , notes.name, ' ' status , COALESCE(contacts.first_name,'') || ' ' || COALESCE(contacts.last_name,'') AS contact_name , notes.contact_id , contacts.assigned_user_id AS contact_name_owner , 'Contacts' AS contact_name_mod, notes.date_modified, ' ' assigned_user_name , ' ' assigned_user_owner , ' ' assigned_user_mod , notes.filename, notes.created_by , 'notes' AS panel_name FROM notes LEFT JOIN contacts AS contacts ON contacts.id= notes.contact_id AND contacts.deleted=0 AND contacts.deleted=0 where ( notes.parent_id= 'd3e15dc6-9525-d1b8-63fb-474f614635fa' AND notes.parent_type='Leads' AND notes.deleted=0) AND notes.deleted=0 ) UNION ALL ( SELECT emails.id , emails.name, emails.status, ' ' AS contact_name , ' ' AS contact_id , ' ' contact_name_owner , ' ' contact_name_mod , emails.date_modified , jt1.user_name AS assigned_user_name , jt1.created_by AS assigned_user_name_owner , 'Users' AS assigned_user_name_mod, ' ' filename , emails.assigned_user_id , 'emails' AS panel_name FROM emails LEFT JOIN users AS jt1 ON jt1.id= emails.assigned_user_id AND jt1.deleted=0 AND jt1.deleted=0 INNER JOIN emails_leads ON (emails.id=emails_leads.email_id AND emails_leads.lead_id='d3e15dc6-9525-d1b8-63fb-474f614635fa') where ( emails_leads.deleted=0 AND emails.deleted=0) AND emails.deleted=0 ) ORDER BY date_modified desc LIMIT 10 OFFSET 0::PostgreSQL error ERROR: syntax error at or near "contact_name_owner" LINE 1: ... ' contact_na... ^

I could only wish I was making this up.


WTF? And I do mean, seriously, WTF?

I've been looking into The Error From Hell, and seeing how I'm given the exact line number where the error occurs, I thought I'd start there.

So, line 136 from include/database/pgsqlManager.php:

$result = pg_query($sql);

Nice.

So, to see the full query that's failing, I decide to print out the query just before it's made. And that's when I realize that the function this line appears in is called several times throughout the program (not all SQL calls are funneled through this function, just enough to make it painful).

Nice.

Okay, approach the problem from a different angle. What's the function that this piece of code is in? Oh, that's easy—query().

Okay, try a different approach.

The error complains about a syntax error near contact_name_owner, so let's try looking for that. Thirty-one loations where it's used, but none of them appear to construct a 3,544 character long SQL statement, and the one place where such a statement might be constructed, isn't called.

Head?

Meet Mr. Desk.

Mr. Desk? Meet my head.

Ouch.

I think I see the problem:

' ' AS contact_name , ' ' AS contact_id , ' ' contact_name_owner

It seems as if there's a few missing ASes in the SQL Statement From Hell, but not knowing where it's constructed (or even how), it's not that easy to fix.

Or rather … there is a way …

Just before I call pg_query(), scan the string, looking for missing ASes and add them as required, maybe using some form of regular expression search and replace funct—[at this point, Sean's head exploded from even entertaining such a notion and was pronounced “mostly dead” at the scene. Further updates as they arrive. —Editor]

Tuesday, Debtember 18, 2007

I still contend it's the bloody PHP programmers …

Sad.

Sad that the easiest way to fix The Error From Hell was to use a search-and-replace function to “fix” the SQL query.

Sigh.

$sql = preg_replace("/\s+\'\s+\'\s+([a-z]+)/"," ' ' AS \\1",$sql);

It's not perfect. It'll break if there's an SQL statement with a lowercase AS. But it'll have to do for now until I find a better regular expression.

To top it all off, I received the following from someone who has worked on porting SugarCRM to PostgreSQL:

The SugarFolk, I think due to rather obtuse source management and procedural policies, aren't interested in folding in my many improvements and PostgreSQL support. I moved on to other employment having nothing at all to do with SugarCRM or PHP (and very little to do with PostgreSQL), so I haven't worked on it. So it's officially dormant.

Sigh.


“Ah, I see you have the machine that goes ‘ping!’”

“No, it was really stupid.” Erik sighed. “I just had the idea that a CD ROM drive in an old system could eject and hit the reset button. It was a ridiculous idea.”

“Wait,” Laura began, “could you really do that?”

It was another uncomfortable moment for Erik, but she seemed serious, so he just went for it. “Uh, yeah, I could, but it's hardly the best solution … I mean, I'd have to position the servers just right, somehow get the heights and alignment correct, and update the polling script to eject the CD ROM drive any time it didn't respond to ping.”

And that was exactly what Erik found himself spending the rest of the afternoon setting up.

ITAPPMONROBOT

Yeah, I can relate

Wednesday, Debtember 19, 2007

Stick this in your power plant, Lake Worthless Utilties!

Toshiba has developed a new class of micro size Nuclear Reactors that is designed to power individual apartment buildings or city blocks. The new reactor, which is only 20 feet by 6 feet, could change everything for small remote communities, small businesses or even a group of neighbors who are fed up with the power companies and want more control over their energy needs.

Toshiba Builds 100x Smaller Micro Nuclear Reactor

And, given that we don't have a home owner's association at Casa New Jersey, we could probably get away with this, too …

Thursday, Debtember 20, 2007

“Code's worst enemy” is code itself

Using about three billion words, Steve Yegge makes the observation that the higher level the code, the less lines it takes to express a program, which is basically a truism in Computer Science. For instance, it's easier to write:

x1 = ((A * y) + B) * x * (1.0 - x)

than it is:

fldc1
fsub	[x]
fld	[A]
fmul	[y]
fadd	[B]
fmul	[x]
fmul
fst	[x1]

In fact, mod_blog would be about three times longer if it were written in Assembly than in C (and to be fair, it might take less code if it were written in Python).

So what Steve says isn't anything new in this regard.

But in Steve's billion line manifesto, he does raise a few points about IDEs that may make my own ideas moot (or a lot less easy to implement generally).

Friday, Debtember 21, 2007

An interesting idea in programming environment

Oh my … now this is brilliant, although you may need to watch the video to grasp the full concept.

Now, before you click on that link, let me warn you it's about a new programming language/paradigm, based upon a two-dimensional way of programming (although, oddly enough, even a two-dimensional programming language isn't new).

It's a neat idea, and the development system presented in the video incorporates ideas on what an IDE should do for you. I can also see using a similar tool that might solve (or at least, points towards a solution) a particularly thorny programming problem that still lacks a good name. How I envision the solution to that as-yet unnamed problem is a list of objects across the top of a table, all possible actions down the left side, and at each intersection, you supply the code to handle that object with that action.

Hmmm … using a spreadsheet as a programming editor …


Forever stumbling across Unix commands

Man, I hate when this happens—I'm browsing around on the Intarwebs, when I come across a reference to what appears to be some obscure Unix command only to find it's been around for close to thirty years now.

Sigh.

That's what I get for not bothering to read up on the 3,300 commands available by default on your typical Unix installation (found by simple invocation of find `echo $PATH | tr : ' '` -type f -perm 755 | wc -l—ain't Unix wonderful?).

Monday, Debtember 24, 2007

Notes from a last minute shopping trip

It's Christmas Eve, although it's hardly the late evening at 6:27 am, but still, saying “Christmas Eve” just rolls off the tongue whereas “the day before Christmas” just kind of lies there like the fruit cake that's been in the family for generations; it's 6:27 am, and I'm stuck in line at the local Wal★Mart.

The Kids are in a Christmas pagent at church later today and Spring thought it migh tbe nice to video tape their performance (The Younger is one of the Three Kings, whereas The Older is playing a donkey, but he gets to narrate the proceedings at the crowded manger). She dug out the camcorder, found the power cord needed fixing (it had been crushed), and all that took was some wire cutters and a soldering iron.

There were a few tapes in the bag with the camera, but upon checking earlier this morning (say, around 3:00 am) it was evident that they were not empty of content. So suffice to say that procuring some fresh video tapes for the camcorder was in order.

And that's how I found myself at the local Wal★Mart at 6:27 am on Christmas Eve, stuck in line at the register. Any later in the day and it would have been worse.

Tuesday, Debtember 25, 2007

Something about a holiday …

[Chugga-chugga-chugga-chugga-choo-choo]

Oh yea, that's it …

Merry
Christmas

Wednesday, Debtember 26, 2007

It keeps on ticking …

I got the following email from Mark today:

From
Mark Grosberg <XXXXXXXXXXXXXXXXX>
To
Sean Conner <sean@conman.org>
Subject
Re: Code review.
Date
Wed, 26 Dec 2007 15:22:47 -0500 (EST)

On Wed, 26 Dec 2007, Sean Conner wrote:

I got it. I haven't done much on the computer the past few days, due to the holiday (kind of a welcome break, actually). I'll be looking it over today so expect a response later on this evening.

Oh okay. I just didn't know if X-Grey was misbehaving or all the mail servers on the net changed or something. I guess just nobody has e-mailed me recently. It is still strange not getting my spam … That was kind of like a constant notification that e-mail was working.

Yeah, I can relate

Thursday, Debtember 27, 2007

“Damn you to hell, Canter & Siegel”

When we first had problems in late 2004 we were sending out 50,000 member-requested emails a week. Since mail functions are so deeply wired into core server technologies the average web engineer has no ideas how many emails are going out. I sure didn't. But now I do. We're sending about 400,000 member-requested emails a week. We've had to dedicate significant amounts of time (and thus money) to become sendmail geeks, mastering the myriad error codes, loopback systems and contact policies of the large mail providers and scripting many back-end and website functions to stay in compliance as best we can. We've even had to retain a mail delivery analysis partner, and still debate if we'll have to pay a third party to send all out emails. If one of us was already a master of sendmail, and had connections at big mail providers this would be easy, but how many people fit that descirption in the average 10 person start-up?

Sending Email is a Big Headache for Small Companies with Popular Websites

The rest of the article goes into how difficult it is for a business to send out mass volumes of (and in this case, it appears to be very legitimate) email and all the tricks they have to do in order to satisfy their customers (who apparently get some form of notification via email).

And as a company that doesn't use email as our primary service (we're a web-hosting company), we still have to deal with some of this crap as we too, get blacklisted and blocked by larger ISPs.

I'm afraid that soon email will only be handled between large companies and anything from an “unregistered” server (read: “from a non-large company that hasn't paid the proper Danegeld jizya bribes licensing fees”) will be dropped. In the end, if we want email, we must submit to the Borg use Gmail and that has me worried.

Friday, Debtember 28, 2007

I should know better than to trust a bank to be “fair”

A decade ago, I found myself at the Orlando Airport at 10:30 pm. The reason behind why I ended up at the Orlando Airport at 10:30 pm in early January is a story in and of itself (the fact that I had to abandon my car in the middle of Georgia just after Christmas should give an indication of how fun that particular trip was) and I had just spent the last of my cash on a one-way ticket to Ft. Lauderdale on the first flight out of Orlando the next morning (it was amazing—it was like the airline knew, right down to the penny, how much money I had on me; I think I had less than a dollar's worth of change after purchasing the ticket). Since the flight was still a few hours away and the thought of sleeping at the airport didn't thrill me, I was overjoyed to realize that a hotel existed on the premises.

Now, at the time, my financial situation wasn't all that stable. I just had my cash reserves wiped out, and my checking account wasn't all that great either. And I knew it. But I figured I could write a check, and by the time the hotel chain attempted to cash said check, a day or two would have passed, giving me enough time to get some cash into the checking account to cover the expense.

I think this used to be called “float” and was a process I've seen used by many an adult growing up.

But that was then, as a small kid. The Banking Industry however, pissed that us mere mortals were able to take advantage of such a loop hole, had in the meantime, closed that particular avenue of financial leverage to us peons (even though that article was written in 2004, I think the process was on the way out back in the late 90s when I tried it). So it was rather surprising when the hotel clerk took my check, ran it through was looked like to me a credit card processor, and informed me that I had “insufficient funds” to obtain a room.

Lovely.

I spent the night sleeping in an uncomfortable chair at the Orlando Airport, and upon arrival in Ft. Lauderdale, was picked up by a fellow cow-orker and we both drove into work. It wasn't until around 6:00 pm the next day that I finally got home.

Fast forward a decade or so. Today I'm at my bank, DonTrustUS First (where their slogan is “We bank on you!”) trying to depost two checks. The first is a tax refund from Uncle Sam that I received a few months ago, but given that it was for less than a typical Yuppie Food Stamp, depositing it wasn't a high priority. The second check was a gift from Dear Old Dad, and it was of a sufficient amount to warrant a visit to DonTrustUS First (remember, “We bank on you!”). I was lucky enough to get just head of a large crowd of people (but not lucky enough to get Cute Teller—bummer).

The teller was having difficulty with the check from Uncle Sam, trying multiple times to run it through the magnetic ink reader and having the computer spit back nonsense. The teller then tried keying in the number directly, but the computer kept insisting that the check was from a “foreign country.”

Somehow, I find it very amusing that the computers at DonTrustUS First thought that the US Treasury Department was a “foreign bank.” The teller was finally able to get the computer to accept the check by informing the computer that, indeed, the US Treasury Department is not a “foreign country” and to accept the check.

The second check, the one from Dear Old Dad, didn't have nearly the problems as the one from Uncle Sam. Although the teller did inform me that there was a “hold” on Dear Old Dad's check. When I inquired why, I was informed that because the check from Dear Old Dad was drawn upon an out-of-state check, it would take a few days to clear.

It would, in fact, take until January 7th!

I'm sorry, but XXXXXXXX!

If some large hotel chain could immediately transfer funds from my checking account to their large coffers, are you, DonTrustUS First, telling me that you are still acting like this is the 19th Century and that exchanging funds with an out-of-state bank takes nearly two weeks because you're limited to the Pony Express? (I hear there's a new thing called a “transcontinental railroad” that will supposedly make cross-country mail take days, instead of the few weeks it formerly took)

XXXXXXXX! XXXXXXXX! XXXXXXXX!

It will probably clear sometime tonight, at which point, you, DonTrustUS First, will sit on the money for ten days collecting interest, and yet you still manage to charge me a quarterly fee? (And let's not even get into the whole “draft overcharge” racket you got going)

XXXXXXXX!


Can a civilian land a jet airliner?

Truth be told, I've never had cable TV, but the Discovery Channel's “MythBusters” series has always struck me as a fun and useful idea for a program. A sort of Snopes.com of the airwaves, it seeks to prove or dispel various urban legends and generally wacky propositions—for example, can a person really become stuck to an airplane toilet seat by flushing it during flight?

With commercial aviation as rich as it is with mysteries and misconceptions, it's perhaps no surprise that plane-related topics are among the show's most frequent. Most recently, hosts Adam Savage and Jamie Hyneman attempted to find out if people with no flight training, namely themselves, could safely land an airliner. Their answer turned out to be yes, probably.

The correct answer, of course, is no, absolutely not. But who am I to quibble?

Via Instapundit, Can someone with no flight training safely land an airliner? Plus: Pilotless planes, overpaid pilots and other aviation myths.

Several years ago I had the opportunity to “fly” an airplane. A friend's girlfriend's father, a flight instructor for the Miami International Airport, invited a bunch of us down to his facility one weekend wherein we all got to “fly” an Airbus 320 commercial jet plane.

Or rather, ride in an incredible simulation of one—the very same simulators they use to train pilots.

Now granted, he was there with us in the “cockpit” telling us what to do, but even so, I found landing the airplane quite easy. In fact, it was much easier to land the Airbus 320 than it ever was to land any number of craft on various microcomputer simulations like Microsoft Flight Simulator. In fact, of the four of us there, three were able to successfully land the craft on the first attempt (and the failure? That was because Chuck didn't approach the runway straight on, and attempted a last ditch maneuver to straighten out since he was too impatient to skip and try again).

Now, I saw the Mythbuster's episode in question, and it was very clear that with no instruction what-so-ever, it can't really be done (as both Adam and Jamie crashed when they attempted to land with no instruction).

But with instructions? Landing one of those modern bad boys is plausible.

Heck, I managed to land one under similar conditions.

Sounds like that pilot up there ate some sour grapes.


Everything is smooth sailing, but when things go wrong, you end up in a hurricane

Oh, and speaking of airline myths, this bit from the article caught my eye:

Insult to injury, Pummer finishes up with that “for a job that technology has made almost fully automated” bit. Pilots themselves are partly to blame for propagating the mythology of cockpit automation, so enamored we tend to be of our high-tech gizmos and sophisticated planes. But again, the knowledge, training and experience required to fly one of these “fully automated” jetliners are vastly more substantial than Pummer and many others would have you believe—especially when there's a problem or emergency. That, more than anything, is what pilots are paid for—not for the routine trip during which nothing out of the ordinary happens, but for the times when something goes wrong.

Can someone with no flight training safely land an airliner? Plus: Pilotless planes, overpaid pilots and other aviation myths.

Heh. Sounds like our servers at The Company. For the most part, they run themselves, and even the <shudder>control panels</shudder> allow one to manage the server. But when things go wrong, they go wrong and it takes a metric buttload of experience to diagnose and fix the problem in those cases (and it's certainly debatable if that's a form of progress or not).

Sunday, Debtember 30, 2007

Oooh! It's Dillinger's Keyboard for real!

[The very latest in keyboard technology]

The Optimus Tactus Keyboard reminds me quite a bit of the keyboard that Dillinger used in the movie Tron:

[You can tell it's not a programmer's keyboard, for it's missing the control and alt keys]
[Although it's still a cool looking keyboard]

And despite it probably having a horrible feel, I still would love to have one.

Heck, I would love to have Dillinger's desk from the movie (here, have another look). The thing is, we now have the technology to do this for real.

Monday, Debtember 31, 2007

I found it amusing, and I think Wlofie can relate to this …

Praying to the Visa God is actually quite a bit more rational than current US immigration policy.

Via Hacker News, The world is not so flat, God of Visas edition

Heh.

Obligatory Picture

An abstract representation of where you're coming from]

Obligatory Contact Info

Obligatory Feeds

Obligatory Links

Obligatory Miscellaneous

Obligatory AI Disclaimer

No AI was used in the making of this site, unless otherwise noted.

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: https://boston.conman.org/, then add the date you are interested in, say 2000/08/01, so that would make the final URL:

https://boston.conman.org/2000/08/01

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.