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.

Saturday, April 01, 2000

Even more investment

Got home late. Got up early. Went to day two of the investment class. Learned just how bizarre the stock market can be, what with stocks following entire stock markets, options, leaps, covered calls and ways to make money if the market is going up, going down or going nowhere.

This should help me invest properly in the stock market.

Afterwards, I drove over to my friend Bob's house for the weekly AD&D game, seeing how it would start in a few hours.

To say I was a zombie by the end of the night is an understatement.

Thursday, April 06, 2000

Just catching up

Mark called, still at work, around 2 am and having a hard time working on the current project under Windows NT. I drove over to his office to hang out with him and act as moral support for the loathsome job.

After he got what he needed working, we spent the next few hours checking out stocks to invest in (using the material I learned in the investment class) and around 8 am, we went to Tom Sawyer's for breakfast.

Tom Sawyer's is a local restaurant like the Cracker Barrel, only not as expensive and without the gift shop. Great food. Great prices.

Came home, and crashed.

Tuesday, April 11, 2000

The Tax Man

The big thing today—last minute updates on my 1040, Schedule D.

Man, taxes are a pain. Not hard, just tedious. Filled in some information, which affected this value, which affected that value, which … well, this is something that a spreadsheet is perfect for. Just punch in some values, wait a few moments, and you now owe Uncle Sam a large check.

Then again, knowing the way things work, it would require a Microsoft product.

Wednesday, April 12, 2000

The Bogus Paper Trail

Just had a conversation with Mark over documentation, or rather, the lack of documentation in our industry.

I thought companies didn't document their products (say, a hardware device for a computer) for one of two lame reasons:

  1. “It'll give our competition an insight into how we did things and therefore they'll steal our R&D from underneath us.”
  2. Their hardware is so crappy they don't want anyone to know just how bad it really is.

But the primary reason, so according to Mark, is that the companies are afraid of releasing the documentation because most of it is incomplete, inaccurate or just doesn't exist to begin with.

And forget trying to get documentation from programmers or engineers—they'll either quit and go elsewhere (where they don't have to document) or what they write will be so horrible that no one actually uses it (which is pretty much status quo from what I understand).

Or, even if the company can release the documentation, it does no good because chances are good that they used products from other companies that don't document what they did, or don't release documentation, or don't release documentation without a thick layer of NDAs to CYA.

So the next time you get that chip from Intel for your next hardware project? Just toss the documentation—it's totally bogus anyway.

Just don't ask about the next bridge you drive over.


invoices

I finally got around to printing an invoice for Atlantic Internet. It's a rather involved process printing out an invoice, but it's not the software that's the problem.

It's the hardware. Or rather, the lack of space for said hardware.

I use an old MS-DOS box for printing of invoices. Nothing difficult, just copy over a template file (which is nothing more than a text file), fill in the columns using a text editor, save then print to a dot matrix printer. The problem is I have no space left for the system so it's been sitting in my bedroom on the floor, waiting for the time I get around to putting it somewhere.

But I needed to print this invoice and the Computer Room is full. Well, not as full as it was, but now that it's orgranized I'd like to keep it that way.

I could hook the printer up to the Linux box, but Unix and peripherals don't mix. Or rather, don't mix well. I don't have an exotic printer. It's dot-matrix. Schlep ASCII out the parallel port and it'll print. But Unix weenies have to make something simple overly complex with half a dozen configuration files (none of which are similar, and don't even get me started on adding a modem to Unix).

Well, that and I never bothered to install the printer subsystem on Linux since I don't use the printer all that often. Last time I dug it out it was early February (when it and the MS-DOS computer were in the Computer Room).

So I quickly set up the computer in the bedroom, printed out the one page I needed, and broke everything down again.

Now I just need to submit the invoice.


So you wanna add a modem to Linux?

Friends that know me know that I tend to get very frustrated when things I think should be simple, or at least straight forward, aren't. This is especially noticible with respect to computers.

And it's one of the reasons I haven't bother to set up printer support under Linux (or Unix in general). Unix weenies chant “Simple. Simple. Simple,” but what they do is “Complex. Complex. Incomprehensible.” I'll take the case of modems under Linux, since I have more than my share of experience with what normally should be rather simple and painless.

Situation: Hook two Linux systems together via modem. Mark and I have done this several times over the years and every time it takes several hours to get it working. The first time it took like 16 hours, but that's because we wasted 12 hours on a core-dumping uugetty (that we didn't know was dumping core).

  1. Plug modem into computer. Even if it's an internal modem and you have to open the system and shove a card in, this is the simple step. But because of the PC hardware you have to make sure you don't have IRQ conflicts, but let's assume you don't. Plug the modem in.
  2. Figure out which port the modem is plugged into. Again, this should be simple and in fact, these two steps are the same reguardless if you are using MS-DOS, Windows, or Linux.
  3. Now figure out if you need to use /dev/cua* or /dev/ttyS*, but it depends upon the Linux kernel you are using. One if for dialing in, one for dialing out, but in a pinch I think you can use either as long as you don't try to have one program answering the phone and another one trying to make an outgoing call.

    For you see, while both /dev/cua* and /dev/ttyS* use the same driver, they have slightly different semantics when opening them up for use and I can never rember what those semantics are (but hey, this is Linux, I can check the source code) or which device is for dialing in or dialing out.

    But the newer Linux kernels (starting with 2.0? 2.2?) have removed that annoying aspect, thus annoying a bunch of package maintainers who content that Linux was doing the Right Thing and this new way of doing things is the Wrong Way.

    See what I mean? And we haven't even gotten the computer and modem talking yet!

  4. Select which getty program you'll be using. mingetty is only used for virtual terminals, but that still leaves:
    • mgetty
    • uugetty
    • getty
    • agetty
    • mgetty
    Don't worry, they're all equally bad. We always ended up using uugetty.
  5. Figure out what configuration file it wants. Usually you think the man page would tell you, but I've found that it's best to grep through the executable for potential configuration file names.
  6. Write the configuration file. Since we're using Hayes compatible modems, the following configuration file for uugetty seems to work:

    TIMEOUT=60
    INIT="" \d+++\dAT\r OK\r\n ATZ\r
    WAITFOR=RING
    CONNECT="" ATA\r CONNECT\s\A
    DELAY=1
    

    The INIT and CONNECT lines are commonly called “chat scripts.” The format is a series of pairs, one string for what to expect as input, the next what to send for output. Notice that if something unexpected comes up you can't do anything about it. Or maybe you can. Best to check the source code.

  7. Next, add an entry to /etc/inittab for uugetty. What I have is:

    
    S1:2345:respawn:/sbin/uugetty ttyS1 F57600
    
    

    The first paramter to uugetty is what device entry to use, minus the /dev part. The second is an entry out of /etc/gettydefsdon't edit this file! For a modem you pretty much want a fixed-baud modem entry, one that is faster than your modem supports since most modems these days can do on the fly compression.

  8. Next, you need to configure the PPP daemon. Under Linux the file you want to edit is /etc/ppp/options. There are a slew of options to configure and through plug-n-pray, Mark and I got the following working:
    -pap
    -chap
    crtscts
    deflate 15,15
    bsdcomp 15,15
    netmask 255.255.255.240		#replace with your netmask
    10.0.0.3:10.0.0.18	#replace with local IP, remote IP
    modem
    passive
    -am
    ipcp-accept-local
    ipcp-accept-remote
    mru	552
    mtu	552
    asyncmap 0
    

    You also need to configure /etc/ppp/ip-up.local with the appropriate routing information. This is a shell script, not a configuration file. Through experimentation, I've found that the shell script has the following parameters:

    1. interface name
    2. tty device
    3. speed
    4. local IP address
    5. remote IP address
    6. extra param—not sure what it's for

    So in this file, I add some commands to get the routing done:

    /sbin/route add -net 208.26.72.16 netmask 255.255.255.240 dw $4
    /sbin/route del $5
    

    You don't need the route for the one IP address so it can be removed safely.

  9. Add a user to the passwd file who has a shell of /usr/sbin/pppd so the other side can log in and establish a PPP connection.

And you're done.

Oh, I forgot to mention, that's only for one half the connection—the one that is accepting incoming calls. Doing the other side is similar but I think I got my point across—this is insane.

Now, for a printer …/p>

Thursday, April 13, 2000

work

More work done on the weblog/journal. More code written. Made a mockup archive of what I've done so far (entry wise). Much more work to be done, but it's getting there.

Updated Sunday, August 25th, 2002

There used to be a link to an archive mockup I had at one point, but I removed it as getting it to work would be a major undertaking. Besides, they layout I did have wasn't working at all, and the number of files I would have to import and fix is prohibitative at this time.


I'm surprised it's still around

It's been awhile since the last VS_O2 update. So why not?

I'm checking up on the forum and I come across this thread about a BASIC compiler for VS_O2. This sums it up pretty well:

Well C programmers have survived for years with a minumum of runtime error handling so I think it would be fine for your compiler to not worry about it either.

It just puts a burden on the programmer to check for things like being out of array bounds and such.

Shudder.


It's sooooooooooooo cute!

Some of the techs at Atlantic Internet bought the new IOpeners from Netpliance. Between two of them they managed to snag four of the devices from a CompUSA up in West Palm Beach (the ones in Miami and Ft. Lauderdale being sold out already).

They're neat devices, out of the box and given a tutorial in less than 30 seconds—a true appliance. And tiny.

The devices they got were the “non-modifiable” ones. Which in essence means they expoxied a modified BIOS to the mother board that doesn't boot from a harddrive. The IDE connector was not clipped.

One of the techs was there at the office for hours trying to get the existing software to dial up to Atlantic Internet with little success.

Friday, April 14, 2000

“That which does not kill us, hurts like hell!”

Mark and I stopped off at Atlantic Internet after a dinner meeting to find one of the techs still there fiddling with his IOpener. We fiddled around with that, then I showed Mark one of the computers a customer I'm doing work for has.

The IOpener is small. The server I showed Mark was not. This is a large machine, dual Pentium III with one gig of RAM (a gigabyte!) and some 30 gigabytes of RAID-5 storage (small these days, I know).

I'm doing some work for this customer and I had noticed that the 30G of storage wasn't mounted on the server. So, as long as I was there, might as well mount the RAID array. Mark, having a RAID array at home, was on hand to help with the consulting.

megaraid: v107 (December 22, 1999)
megaraid: found 0x101e:0x9010:idx 0:bus 0:slot 9:func 0
scsi0 : Found a MegaRAID controller at 0xd810, IRQ: 17
megaraid: [UF80:1.61] detected 1 logical drives
scsi0 : AMI MegaRAID UF80 254 commands 16 targs 1 chans 8 luns
scsi : 1 host.
scsi0: scanning channel 1 for devices.
scsi0: scanning virtual channel for logical drives.
  Vendor: MegaRAID  Model: LD0 RAID5 35000R  Rev: UF80
  Type:   Direct-Access                      ANSI SCSI revision: 02
Detected scsi disk sda at scsi0, channel 1, id 0, lun 0
SCSI device sda: hdwr sector= 512 bytes. Sectors= 71680000 [35000 MB] [35.0
GB]
 sda: sda1 sda2 sda3 <sda5 sda6 sda7>
(scsi1) <ADAPTEC AIC-7890/1 ULTRA2 SCSI HOST ADAPTER> found at PCI 12/0
(scsi1) Wide Channel, SCSI ID=7, 32/255 SCBs
(scsi1) Downloading sequencer code... 385 instructions downloaded
scsi1 : Adaptec AHA274x/284x/294x (EISA/VLB/PCI-Fast SCSI) 5.1.23/3.2.4
       <ADAPTEC AIC-7890/1 ULTRA2 SCSI HOST ADAPTER>
scsi : 2 hosts.

From that, it looked like there were two disk controllers. The system was booting from SCSI, that much was apparent. What wasn't apparent was the location of the RAID system.

The BIOS POST also gave the impression of two controllers. We went into the RAID BIOS extention, initialized the RAID controller and drives and then rebooted the system.

Turns out that the megaraid and the Adaptec SCSI controller are one in the same and that the system itself (it runs Linux) was booting off the RAID controller!

It is through our mistakes that we learn.

And it is through grovelling that we retain our customers.

Fortunately, the customer didn't loose any important data (the customer wasn't using it fully at the time), nor did he mind that much (“Next time, please consult with me before you do any irrepairable configuration changes. Okay?”).

That, and I didn't like the way Linux was installed on the box to begin with.


“Don't Panic!”

While Mark and I were doing a fast recovery of a customer machine we received a call from John, the paper millionaire of a dotcom company and former member of a Grateful Dead cover band to say he couldn't get to his servers, located in the very same co-location facility we were currently at.

Mark goes over to John's machines. All servers are up, but he can't ping out. In fact, he can't get past the first hop. Mark then heads over to the core room, I remain in the co-location room, and we all get on a conference call.

Network seems okay—link light is on at both ends of the connection. No traffic. Jiggle the cord. Oh! A few packets. Then major lossage again. Repeat.

John is freaking out because he needs to be on a plane early and it's now 3:30 am or there abouts. He finally conferences in the main sysadmin for Atlantic Internet because Mark and I can't figure out what's going on.

Neither could the sysadmin. Everything seems okay. Only there's no traffic. John, panicing is yelling at Mark. Mark is yelling back at John not to panic. Meanwhile we can barely hear the sysadmin over the conference call. Pandemonium reigns.

I quickly grab the network analyzer they have (way too cool) an hook it to John's side of the connection. It lights up like a Christmas tree. Low utilization, high collisions and an even larger rate of errors. I then take the unit to the Atlantic Internet side. Nothing. Normal traffic from John's servers.

We then plug the network analyzer into the Cisco Catalyst 5000 which is serving as the main switch. Actually, it's more like three switched hubs than a real switch—there are 24 ports grouped into three sections. Each section is a hub, but switched between sections.

The network analyzer lights up like a Christmas tree.

The consensus seems to be that the Catalyst is hosed. It probably didn't survive a DoS attack a few days previously and was slowly going bad. So it was some quick work to rerun a few cables to nearby switches and remove the Catalyst from service.

Mark and I didn't leave the office until 5 am.

Saturday, April 15, 2000

Thirty-something

My friend Tom (the architect) had his birthday party today. The Big Three-Oh. Lots of fun, and lots of toys (noise makers, bubble makers, Groucho Glasses, Nerd Glasses and other novelties).

As my friend Hoade would say, “He's now rocketing towards fourty!”

Sunday, April 16, 2000

Baby shopping

(originally written on Tuedsday, April 11, 2000)

I actually went to Babies-backwards-R-Us. My friend Lorie is having a baby shower and everyone (including guys) were invited, as I think she has more male friends than female friends.

She was registered so that helped. It was actually quite painless. Entered the store. Next to the customer service desk was a kiosk—an embeded computer with touch screen. Press here to start. Type in the name (bad point—keyboard presented was in alphabetical order not QWERTY—very annoying), found her record, hit print and a few seconds later seven sheets of printout describing what she wanted.

That was the easy part. Hard part was actually finding stuff on the list.

Now, those that know me will find it rather difficult to believe that I actually did this. But I don't hate kids. I mean, if they're cooked just right … ha ha only joking.

But I'm amazed at just the amount of stuff you can get for a baby. Special rash prevention diapers. Special formula bottles. Pacifiers. I did not realize the extent of specialization in pacifiers. Nor baby mits (now when did they become popular?).

Makes me wonder how we ever survived as a species without it?


Never fold a kangaroo

I wrapped the presents for Lorie's baby shower and I wanted to do something … different for the bow.

I have an interest in origami, and one of the books I have gives the instructions for folding a kangaroo and baby and I thought that would be a nice bow; something that is different.

So I grab the book and some origami paper. Quickly glancing through the book it looks easy enough.

Until you actually do it.

Since this is the third work in the series to be made from it, instructions for folding the bird base are not given.

Instruction between steps one and two of kangaroo and baby (nice).

I've found that the instructions for origami tend to follow the Unix man page model: it makes sense once you know how to do it. But if you don't know how it works then getting from (say) step 23 to 24 may take some time.

Step 23 is making one of the last folds for the head of the kangaroo. Okay, I see a valley fold here, a mountain fold there but how does that get from the illustration in step 23 to the illustration in step 24? That one step alone took me more than an hour to get.

My first attempt ended up looking more like an aroused male mutant kangaroo than a female kangaroo with a baby.

It only took me four hours to make the bow.


Baby shower

So I arrive at Lorie's baby shower. There's some concern that she may not show up since she wasn't feeling well the day before, but eventually she showed up with husband in tow (and baby still in womb).

I'm not sure what exactly I expected, but it was fun. And, unusual for a baby shower (I'm guessing) is that there were more males than females at the party.

And Lorie did like the origami kangaroo I used as a bow.

Monday, April 17, 2000

Titus Andronicus

My friend Kurt and I went to see Titus, a film based on the Shakesperean play “Titus Andronicus.”

Kurt mentioned the film at Lorie's baby shower and since he has the week off (being a high school English teacher and this being Spring Break) he asked if I wanted to go see it.

Sure, why not?

I started reading the play the night before, but only got about halfway through Act II. The language is particularly difficult and it was often hard to determine how the lines should be delivered. Seeing Shakespear is better than reading it.

It's not one of Shakespear's better plays, but it may very well be his bloodiest—discounting Titus' 21 dead sons at the start, the body count is twelve.

Why yes, it is a Shakespearean tragedy where everybody dies. Not only that, but Titus kills one of his sons in a fit of rage. His daughter has her tongue cut out and hand chopped off after being raped. Titus cuts his own hand off in a cruel joke. The Emporess' two sons are killed, cooked and served to her as dinner. A nurse is killed to keep secret the birth of an illegitamite baby.

Very bloody.

And the style of filming was very unique—blending Classical Rome with the Swinging 20s and an indeterminate future setting. Sounds odd but it works in the film.

And Anthony Hopkins as Titus and Jessica Lang as Tamora were excellent. Well worth seeing if you can.

Wednesday, April 19, 2000

Substance, Structure and Style

More work on mod_blog today. Had a discussion with Mark about separating the style from the module. As it stands, I'm not sure what to do about outputing the pages. Ideally I would have templates that would describe the look and feel of the pages, but I have no idea where to do.

My webserver does have PHP installed, but I don't know enough about the internals to hook into it. I'm relunctant to do this in PHP entirely, as parts of what I'm doing are messy enough in C (and no, I don't think Perl's regexs can cut it).

But it does look like I'll have to include some form of scripting language to handle what I want cleanly.

But HTML isn't exactly designed as a scripting language, nor embedding one within HTML the best idea. That's another reason why I want to stay away from PHP or MetaHTML, because of the mixing of scripting with output—any formatting in the code is lost (more or less) when you embed HTML (or any large form of output) in the middle of it. I find it difficult to follow such code.

But Mark came up with an idea I'm pursuing. Turn the problem inside out more or less, or rather, separate the large chunks of output from the scripting. So, for instance, the HTML:

<chunk name="foobar">
        <img 
                src="## graphic name ##" 
                alt="## graphic alt ##" 
                width="## graphic width ##"
                height="## graphic height ##"
        >
        Today's Date: ## today-date ##
</chunk>

And the scripting (in a hypthetical language which doesn't bear any relationship to what I may end up looking like):

object graphic
{
	string name;
	string alt;
	int    width;
	int    height;

	proc name   { print name   };
	proc alt    { print alt    };
	proc width  { print width  };
	proc height { print height };
};

proc today-date { print gettime(); };

graphic name   ="foobar.gif";
graphic alt    ="[nothing here to see]";
graphic width  =imagewidth('foobar.gif');
graphic height =imageheight('foobar.gif');

display_chunk('foobar');

Namely, in the HTML, anything between the double hash marks is a call to a scripting object (or procedure). The scripts themselves can output chunks of HTML, which may include scripting callbacks, as seen here.

Again, that's probably not how the scripting language will look ultimately, and for now I think I'm just going to embed the HTML within mod_blog just to get it out there and running. That's not to say I couldn't get this out with an embedded scripting language, but some of the tools I want to use I still have to clear before I can use them and rewriting the tools is going to take time.

The reason for rewriting the tools taking quite a bit of time has to deal with error detection and recovery, which is another aspect of conversation Mark and I are hashing out.


“And some call me … Harry!”

I borrowed J. K. Rowling's Harry Potter and the Sorcerer's Stone from my friend Jeff. Cute book and I can see why it would appeal to kids, in that “These are not my parents there must be some mistake I'm probably a prince or princess who has been kidnapped or something” way.

But I do have several questions about the underlying themes of the story so if you don't want possible spoilers about this story, skip this entry.

The first has to do with Hogwarts itself. It consists of four houses, one of which, Slytherin, is known to produce evil (or not entirely nice) wizards (the most notorius being Voldemort, the wizard responsible for killing Harry's parents.

I would think that after the whole Voldemort affair (which took place 11 years prior to the main story) that the Headmaster of Hogwarts would disband Slytherin, especially since in the main story, most of the kids in that house are of the most disagreeable sort.

The second has to do with the whole concept of Hogwarts. The wizards and witches who attend seem for the most part to exist apart from the rest of society, much like the obscenely rich seem to exist apart from the rest of society and don't participate much in the affairs of mortal men (or something to that effect). And the term the magically gifted use to describe those lacking in the magic arts—Muggles—seems a bit, dare I say, racist? Perhaps it's just me.

But on the whole, an enjoyable and fast read.

Thursday, April 20, 2000

The Day We Met Jim Davis!

It was nineteen years ago that Hoade and I met Jim Davis, creator of Garfield.

Back then, Hoade and I were huge fans of Jim Davis, and we both had asprirations of being cartoonists ourselves. When we found out that Jim Davis was going to be at the local bookstore (at the Lauderdale Lakes Mall in Lauderdale Lakes, Florida. Alas it is no longer, having been transformed over the past nineteen years to a strip mall).

We were elated until we found out that the 20th of April fell on a Monday and that our parents would most likely not let us skip school (let's see … 1981 … that would put us in the 6th grade). But fortunately, Easter that year fell on the 19th which meant we had the following monday, the 20th off and we could go meet our idol—Jim Davis!

My maternal grandfather drove us the few miles to the Lauderdale Lakes Mall, were we promptly got in line with our Garfield books (I think there were only three out by that time) and a few samples of our work.

At 2:32 pm, Eastern we met Jim Davis! He not only signed our books but our sample cartoons as well! Being the two youngest people at the signing brought us to the attention of a Miami Herald reporter and we ended up being profiled. They even printed Hoade's cartoon in the newspaper (I would link to the article, but I think being nineteen years ago it might not be available via the web).

Since then we've gone on to careers other than cartooning.


“Seven Girlfriends”

Normally I have a weekly dinner meeting with Chuck about a small side project we're working on. But this week it was canceled, and my friend Jeff's fiance was given four tickets to see a preview of Seven Girlfriends, a movie about a man who has a breakup with his girlfriend and he goes on a journey to see what went wrong with his past girlfriends.

Okay, so it sounds like High Fidelity and in some ways it is similar. Much like Deep Impact and Armageddon are similar.

But this was interesting not because of the film (which is quite good and rather funny, although at times it's a bit of dark humor) but because both the director of the film, Paul Lazarus and the main star of the film, Timothy Daly, were both at the viewing to help promote the film. Tim Daly is quite funny in person (“This film was the … latest film I've done …”) and Paul Lazarus reminded me of a younger Richard Gere.

Friday, April 21, 2000

Ring ring

There is nothing quite like waking up to a constant barrage of phone calls from a client. Sigh. How did he ever get my home phone number?

Don't answer, it's retorical anyway …

Saturday, April 22, 2000

Fried Chicken

So this week I've been picked to cook dinner for the weekly gaming session on Saturdays. No problem. Large group of people, something easy … let's see … I know … fried chicked!

And no, I did not go to KFC and buy a bucket of Extra-Crispy thank you very much. I made fried chicked from scratch. It isn't hard, and having spent many years watching my Great Aunt (Mom's aunt) Freddie (and yes, that's her real name) fry chicken I knew how to do it.

The cookbook I have, the Culinary Arts Institute Encyclopedic Cookbook, lists the recipe under Fried Prairie Chicken. The basic recipe is wash the chicken pieces in cold water, drain. Coat with milk, then coat in flour and fry for about 40 to 45 minutes, turning once halfway through.

That's it. Pretty simple.

The only problem I had was I miscalulated the time it would take to cook all the chicken I had and ended up being a bit late.

And the chicken went over well. So did the mashed potatoes (peel and boil potatoes until cooked. Drain, then mash with a bit of milk and butter to desired consistancy. Allow one potato per serving).

Tuesday, April 25, 2000

More Scripting HTML

Via Camworld is an article about JSP which from reading the article, tries to serve the same purpose as what I was talking about a few days ago.

That in turn pointed to webmacro which seems to do templating, but I'm reading further.


Associations are eeeeeeeeeeeeeeeeeeeeeeeevil!

Around this time each month I pay my bills. This is also the time I catch up on unread snail mail so it was today when I found a notice from The Association concerning an amendment to Article 20 of the Declaration of Condominium of my particular area.

The proposed amendments are actually deletions from the current Article 20, which if passed, means that Unit Owners (that's me) will no longer be allowed to lease or rent their respective units, in three legal size pages. Yes, Article 20 of the Declaration of Condominium is three legal size pages long.

It's bad enough I don't own any actual land (I don't. I own a volume of space sharply deliniated by the ground, the upstairs neighbor and the outer walls of my unit). It's also bad that I'm personally responsible for much of the additions to Rule 5 of the Rules and Regulations of the Association. Now this.

I tell you, associations are eeeeeeeeeeevil!


Rule 5.

Just in case you are curious, here is Rule 5 (of 30) from the Rules and Regulations of The Association:

(5) NO vehicles other than automobiles shall be permitted to park within the Condominium Property, except for the purpose of making deliveries or providing repair services to a Unit. For purposes of this rule, “automobile” does not include any type of van (except those vans with windows all around AND two (2) or more rows of seats), camper, truck, motorcycle, commercial vehicle, etc. No vehicle which can not operate on its own power shall remain on the Condominium Property for more than twenty four [sic] (24) hours. [I think I'm responsible for having the power clause added. -spc] No vehicle shall be repaired within the Condominium Property, except in emergencies. Head-in parking only is permitted. Please be informed that your Board of Directors in order to maintain the beauty of our village has promulgated rules so that illegally or improperly parked vehicles be ``towed off'' Association property at the expense of the Owner [Note: first reference to towing at owner's expense. -spc] of the offending vehicle and that appropriate signs indicating the above have been posted at the ingress and egress (entrance and exit) [I just love how they used fancy terms then had to go and define them. -spc] to the property in accordance with Florida Statutes. Therefore effective on or after April 1, 1989, an authorized representative of the Board of Directors or the Management Company will exercise the right of The Associations to have any unauthorized or improperly parked vehicle on Association property towed away at the expense of the owner of the vehicle involved. [Note: here it is again. Sigh. -spc] Identification of vehicles in violation as noted above should be brought to the attention of the Management Company or the Board of Directors who will then take appropriate action. [Which shall consist of a large obnoxious orange sticker adheared to the driver side window of said car that will require a razor blade to remove. Trust me, I know of which I speak. -spc] Any vehicle in violation of the above will be given twenty four [sic] (24) hours notice. Thereafter it will be towed at the owner's expense. [Third reference! “What I say three times is true!” –Lewis Carrol -spc] Please govern yourself accordingly. These rules will be strictly enforced. [And how! -spc] Vehicles will also be towed [Number four. -spc] if the vehicle is parked on the median, lawn or landscaped areas or the vehicle is parked in a parking space which is reserved for, and/or numbered for a Unit Owner/renter [sic] [Well, I guess that will have to be amended after Article 20 is amended. -spc] that has not authorized said vehicle to park in that Unit's designated parking space.

Whew!

I also particularly like Rule 16 (which I am not responsible for thankfully):

(16) No one other than persons authorized by the Board shall be permitted at any time on the roof of the Condominium Building.

I would just love to hear the story as to why Rule 16 was needed.


Speed

I should also mention that this was the day I got a speeding ticket driving home.

I knew better than to take Sample Road, which is under heavy construction, but I figured that hey, it's like 1:30 am and there is no traffic what so ever. That and well … I needed to get home. Nature calling and all that (and I mean, it was calling).

So I'm speeding home along Sample. “Just a few more miles. Just a few more miles. Just a few more miles,” was the mantra I kept saying to myself when WHAM! Off to the right side, on the shoulder, blue lights.

He caught me. Fair and square. I don't put up a fight as it only pisses off the cop and I've found that generally if you take a positive attitude you get off with a warning. But going the speed I was in the zone I was in (construction) meant I probably wasn't going to get a warning.

I didn't.

But it could have been worse. It could have been 1:30 pm (of course, I wouldn't be able to drive the speed I was if it had been 1:30 pm).

But neither did it take that long, for which I was grateful.

Wednesday, April 26, 2000

Woo hoo! Bug free the first time through …

It's always nice when code I write works the first time.

mod_blog advancing yet some more. I was going to embed the HTML within the module, but when I wrote some sample code (to make the archives on the current site) it just got real messy real quick and I didn't even bother finishing it up.

Instead, I quickly wrote code to process template files. This side works pretty much like I think I'm going to end up doing it. I set up a subdirectory containing the templates, each file containing just a portion of a much larger page. In effect, each file is a chunk of HTML code that is processed. During the processing, anything between double hash signs is taken as the name of a callback function.

So for example, in the HTML code I have:

<html>
<head>

  <title>##title## - The Boston Diaries - Captain Napalm<title>

</head>

And the callbacks are currently defined in C as such:

static void archive_callback(FILE *fpout,void *data)
{
  struct tm *ptm = data;
  char       date[BUFSIZ];

  strftime(date,BUFSIZ,"%B %Y",ptm);
  fprintf(fpout,"%s",date);
}

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

void do_archive(
		  FILE *fpout,
                  int   year,
		  int   month,
                  int   stday,
                  int   endday)
{
  static struct chunk_callback cb 
    = { "title" , archive_callback };
  struct tm thisday;

  /* code to set thisday properly snipped */

  ChunkProcess(fpout,"archivehead",&cb,1,&thisday);
  ChunkProcess(fpout,"bostontitle",NULL,0,NULL);
  ChunkProcess(fpout,"bartitle",&cb,1,&thisday);
  
  /* code to generate links for each day */

  ChunkProcess(fpout,"end",NULL,0,NULL);
}

The call to ChunkProcess() takes an output file, the name of the chunk to display, a structure declaring the callbacks, the size of that array, and an extra pointer that is passed to the callback, in this case, to a struct tm * to the date we're processing.

The only thing I may change is the way callbacks are registered, but the mechanics certainly work.


Walkthrough

Now, how did I go about writing 145 lines of bug-free C code to implement the chunk mechanism? Easy. I broke it down into simpler steps. The main routine, ChunkProcess() takes five parameters, an output file, the name of the chunk, the callbacks, number of callbacks, and an arbitrary pointer to data passed back to the callbacks.

So, basically, we have:

int (ChunkProcess)(
                    FILE                  *fpout,
                    char                  *name,
                    struct chunk_callback *pcc,
                    size_t                 scc,
                    void                  *data
                  )
{
  char  fname[FILENAME_LEN];
  FILE *fpin;
  int   c;

  assert(fpout != NULL);
  assert(name  != NULL);
  assert(pcc   != NULL);
  assert(scc   >  0);

  sprintf(fname,"chunks/%s",name);
  fpin = fopen(fname,"r");
  if (fpin == NULL)
    return(CHUNKERR_OPEN);

  while(1)
  {
    c = fgetc(fpin);
    if (c == '#')
    {
      c = fgetc(fpin);
      if (c == '#')
      {
        chunk_handle(fpin,fpout,pcc,scc,data);
        continue;
      }

      fputc('#',fpout);
    }
  
    if (c == EOF) break;
    fputc(c,fpout);
  }
 
  fclose(fpin);
  return(ERR_OKAY);
}

I just basically look for two consecutive hash marks, and if I find them, I call chunk_handle() to do the work for me (I should note my convention I'm using here—StudlyCaps has external linkage, visible to other modules. lower_case is local to this module). So we now have:

static void chunk_handle(
                          FILE                  *fpin,
                          FILE                  *fpout,
                          struct chunk_callback *pcc,
                          size_t                 scc,
                          void                  *data
                        )
{
  char  cmdbuf[BUFSIZ];
  char *cmd;
  char *p;

  assert(fpin  != NULL);
  assert(fpout != NULL);
  assert(pcc   != NULL);
  assert(scc   >  0);

  chunk_readcallback(fpin,cmdbuf,BUFSIZ);

  for (
        p = cmdbuf ; 
        (cmd = strtok(p," \t\v\r\n")) != NULL ; 
        p = NULL 
      )
  {
    chunk_docallback(fpout,cmd,pcc,scc,data);
  }
}

chunk_readcallback() reads the text just past the double hash mark to the following double hash mark. Then using strtok() (easy since it's there, I know how to use it and I'm not worried about threading issues yet) I break it up. This allows us to specify multiple callbacks within a single entry and for each callback, we find it and call the function.

static void chunk_docallback(
                              FILE                  *fpout,
                              char                  *cmd,
                              struct chunk_callback *pcc,
                              size_t                 scc,
                              void                  *data
                            )
{
  int i;

  assert(fpout != NULL);
  assert(cmd   != NULL);
  assert(pcc   != NULL);
  assert(scc   >  0);

  for (i = 0 ; i < SCC ; i++)
  {
    if (strcmp(cmd,pcc[i].name) == 0)
    {
      (*pcc->callback)(fpout,data);
      return;
    }
  }
  fprintf(fpout,"##processing error - can't find [%s] ##",cmd);
}

Again, since I'm just playing around and want something that works, the linear scan doesn't scale, but since I'm not planning on having a dozen or more callbacks, it doesn't hurt. It can be changed easily though since we do pass in the size of the array and as long as it's noted that the array should be sorted alphabetically we can later change to a binary search.

I'm not sure if a hash table is the way to go at this point—that might require a different way of passing in or registering the callbacks, and as it stands right now, I can use the same templates and have different code for the callbacks. The chunk “bartitle” which I defined is used all over the place, and the title itself may not be a date, so the ability to change what ##title## does depending upon what I'm displaying is crucial—I just pass in a different callback array.

The fprintf() is there for diagnostics—I can leave it out with the effect of undefined callbacks don't generate any output at all, but there is no notification of the undefined callback either. I put it in but another way of handling it might be to print out the callback as found in the text, between double hashmarks.

And that's it. The code for chunk_readcallback() is easy enough to leave it as an exercise for the reader, as well as the definition of struct callback.

The trick is just breaking it up into simple pieces.

Friday, April 28, 2000

“Plan to throw one away. You will anyway … ”

So I'm plugging away at mod_blog, slowly putting the pieces together first into a standalone program, then after that works, start the actual process of writing the Apache module.

What I'm finding is that I have a very large mess on my hands right now. I've developed the pieces pretty much in isolation and I'm finding that wasn't probably the best idea, but since I have no idea what I'm doing anyway, the point might be moot.

What I have right now are the following pieces:

  1. Code to retrieve and store the entries. It works fine, except I'm not all tha thrilled with using Standard C's struct tm to reference entries. It's one of those “it's almost useful but not quite” type problems. The definition of struct tm is:

    int tm_sec;	/* seconds after the minute (0 .. 61*)	*/
    int tm_min;	/* minutes after the hour (0 .. 59) 	*/
    int tm_hour;	/* hours since midnight (0 .. 23)	*/
    int tm_mday;	/* day of the month (0 .. 31)		*/
    int tm_mon;	/* months since January (0 .. 11)	*/
    int tm_year;	/* years since 1900		*/
    int tm_wday;	/* days since Sunday (0 .. 6)		*/
    int tm_yday;	/* days since January 1 (0 .. 365**)	*/
    int tm_isdst;	/* DST flag				*/
    

    * Allows up to two leap seconds.

    ** But the standard doesn't say anything about leap years. Sigh.

    And there are calls to convert struct tm to time_t and back again, but years since 1900? Months since January? What were they thinking? But reading the Standard is helpful. For instance, mktime() takes a struct tm * and returns a time_t. But it also normalizes the values in struct tm * so you can add say, seven days to tm_mday, call mktime() and have the structure renormalized.

    Then there's the problem of comparing dates. The Standard just says that time_t is an arithmetic type, which means it can be either an interger or floating point type. With integer types, you can do meaningful comparrisons for equality, but all bets are off for floating point values.

    Sure, you may think modern floating point hardware can give meaningful results when doing an equivalence comparrison, but you can't really. For instance, sin() is a cyclic function over the range [0 ‥ 2pi] (or is it (0 ‥ 2pi)? I can't remember if [] or () mark inclusive ranges) so that sin(0) == sin(2pi) == sin(4pi) … right?

    #include <math.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    int main(void)
    {
      double pi2   = acos(0.0) * 4.0;	/* 2pi */
      double c     = sin(0.0);
      double a     = 0.0;
      double r;
      double d;
      
      for ( ; ; )
      {
        r = sin(a);
        d = c - r;
        printf("%e\n",d);
        a += pi2;
      }
      return(EXIT_SUCCESS);
    }
    

    I ran that on my system (AMD 586) and well …

    [spc]linus:/tmp>a.out | more
    0.000000e+00
    2.449213e-16
    4.898425e-16
    7.347638e-16
    9.796851e-16
    1.224606e-15
    

    I even tried using the constant 2pi and I got even worse results.

  2. Code to handle what I call tumblers. It's about the sixth or seventh revision of the code and it still isn't quite what I need. Problem here is one of solving a generalized problem. I had this discussion with Mark about the definition of a tumbler. I don't want a fixed separator for a variety of reasons (namely one, user entry. Mark hates user interface so he's like “Just pick a single character and that's that!” But that isn't that for what I want to do. And it's causing problems. Using the same code, I want it to accept

    Genesis.1:15

    and

    2000/4/5.2

    as correct, yet if you type in

    Genesis:1.15

    and

    2000.4.5/2

    Know those are valid but need to be corrected (and in this case, sent a redirect back to the user's browser). I have an idea but it requires changes for it to work. So for now I'm going with what I have. The external interface shouldn't change that much (and knowing Mark, he'll be going “I told you so!”)

    Then again, this is a person who would rather use an embedded operating system for a phone switch to do word processing rather than trust his data to an operating system doesn't even bother with error analysis, like Unix (then again, it's not like Mark does word processing either …)

  3. Code to process HTML templates. What I have works nice, but I'm thinking if I really want the ability to include other chunks in chunks. But that breaks the method I'm using now, since you can only specify a callback, but not a callback with data specified in the HTML chunk.

    I have to think about this one.

So I have the pieces. But it's pretty much a mess right now.

Then again, this is the one I'll be throwing away.

Saturday, April 29, 2000

“Does this mean he'll have seven years bad luck?”

I got a call from Lenee the other day. She's the wife of John the paper millionaire of a dotcom and she wanted to know if I would help with their garage sale to get rid of some stuff before they move into their new home.

I agreed, on the condition I didn't have to arrive at 9:00 am. She said to show up at any time, preferrably before the garage sale ended.

I managed to arrive around 1:00 pm, beating Mark. It was pretty much finished by that time; only a few items left that their neighbor bought.

While it was no one person's fault, a mirror did get broken, and Lenee was highly upset over the incident. Okay, so it would cost about $75 to replace the mirror, but no one was hurt, and the piece of furniture wasn't damaged (other than the broken mirror). It could have been a lot worse.

Afterwards we left for lunch/dinner where the topic of conversation dealt with the broken mirror. Sigh.


Lifestyles of the Paper Millionaires of Dotcoms

After dinner John the paper millionaire of a dotcom and his wife, Lenee, took us to see their new home in North Boca Raton.

To say that this house is impressive is an understatement.

Driving through the development Lenee kept pointing out “tear downs”—homes that were designated to be torn down and replaced with new homes. By “old” it was on the order of twenty or thirty years.

Why yes, this is South Florida.

Driving up to The House I was struck with the fountain out front, behind which is the covered walkway to the front door (much the same set up that hotels have). The front entry are two 10 foot doors, leading into a front entry way 50 feet high and marble.

Everywhere there is marble. Keep that in mind. Marble.

The ceilings are an average of 30 feet high. Vast expanses of rooms. And marble. Did I mention the marble?

The kitchen is fairly large, with restaurant style refridgerator and freezer (with digital readout of tempurature). Two dishwashers, a central island with sink and counter space and cabinets everywhere. Gas oven with an electric grill to one side (with attachments for deep friers, steamers, etc. etc.). A butler's pantry and a walk in pantry.

The upstairs has a central open area with three rooms, each with a full bath. Oh, that's the Kid's Wing, by the way.

A wash room with multiple sinks. Another room set aside for office records. Cooridoors everywhere. Oh, and did I mention the marble?

Now, the other side of the house. John the paper millionaire of a dotcom's office. French doors leading into the office, and on the other side of the office, another set of French doors leading outside. It's about 20 by 30 and covered with wood paneling. Cherry wood paneling. Floor to ceiling cherry wood paneling. Did I mention that the ceiling is 30 foot? Beautiful.

The master bedroom. Enter through a large archway. Oh, did I neglect to mention the archways throughout the house? The only room larger is the main living room. Off to one side is a sitting area that Lenee has appropriated. Walking back the other way leads to a hallway which the master closets and master bath sit off from.

The master closest is about the size of your average bedroom. Shelves everywhere, with rods that pull out to hang stuff on. In the center is a custom built dresser with drawers on both sides.

Oh, that's just John's closet. Lenee's used to be the one car garage on that side of the house (the other side has the three car garage).

Now, the master bath. Large room. Did I mention the 30 foot ceilings? Two smaller rooms off to one side in the bathroom—His and Her water closests (Hers contains a bidet. I did ask for a demonstration, never seeing one). Two complete sets of sinks and cabinets, a huge tub and a shower unit that they're going to convert to a steam room.

Did I mention the marble?

The house sits on the edge of lake and they do have a small dock. John is also planning on relandscaping the backyard, and installing a waterfall to cut down on the traffic noise (which you have to listen closely to even hear in the first place).

Now, this isn't your typical house. The development isn't your normal development. The cheapest house costs around $1 million, maybe. Their house was a steal (10,000 square foot house) for $2.3 million.

Did I mention the marble?

Sunday, April 30, 2000

An interactive dictionary

This is HyperFlow, an evolving hypertextual dictionary. It is in an experimental phase, and should be considered absolutely not ready for public release. However you can play with it all you like. Feel free to explore and to create! Just click on a word and see what happens!

Via a Slashdot article about interactive projects.

An interesting concept and one that I might want to play around with some more, maybe even do one myself.

I have had thoughts about doing a dictionary along the lines of what I'm working on, but there are issues dealing with a dictionary that I want to consider first.

Obligatory Picture

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

Obligatory Contact Info

Obligatory Feeds

Obligatory Links

Obligatory Miscellaneous

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

The dates are the permanent links to that day's entries (or entry, if there is only one entry). The titles are the permanent links to that entry only. The format for the links are simple: Start with the base link for this site: 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.