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, 2018

On the plus side, we'll only have to endure eleven months of campaigning this year

The fireworks and explosions have finally ended and that can mean only one thing—

HAPPY NEW YEAR!

Wednesday, January 03, 2018

Notes on an overheard phone conversation with an unexpected observation about a name

Ring.

Ring.

“Hello?”

“Hi. I'm calling on behalf of a national marketing firm to see if you quality for a study group that will pay you $500 for your opinions. What is your name?”

“Sean Conner. That's S-E-A-N. C-O-N-N-E-R.”

“You must get a lot of jokes about The Terminator.”

“Actually, you are the first one! If there are jokes, it's about James Bond, although that's actually rare.”

“Oh!”


Notes on a second overheard phone conversation shortly after a previous overheard phone conversation with an unexpected observation about a name

Ring.

Ring.

“Hello?”

“Hi. I'm calling on behalf of a national marketing firm to see if you quality for a study group that will pay you $500 for your opinions. What is your name?”

“Um … I'm afraid you, that's you in the company sense, not you in the personal sense, but well … it is you in the personal sense, because just called me.”

“I did? Oh! I did! I'm sorry, I forgot to mark your number as being called!”

Monday, January 08, 2018

For some strange reason I feel compelled to relate some random facts about today

I learned a weird fact about today—January 8th is less likely to occur on a Monday than any other day of the week. It's more likely to occur on a Tuesday than a Monday.

Fancy that.

It's also the feast day for Our Lady of Prompt Succor, who apparently helped Andrew Jackson fend off the British army in the Battle of New Orleans, thus indirectly responsible for the formation of the Democratic Party, also on this day, which at the time, was of course a Tuesday.

It's also the birthday of a minor deity (again a Tuesday) but you knew that already.

Tuesday, January 09, 2018

So tonight I'm gonna Internet like it's 1993

A few days ago I recived this email (which was not directly addressed to me):

From
Rouan Lucas van Ryn <XXXXXXXXXXXXXXXX>
To
XXXXXXXXXXXXXXX
Subject
The Gopherspace Cookbook
Date
Sat, 6 Jan 2018 08:47:45 +0000

Greetings good people,

I have recently created a new Gopher hole, known as The Gopherspace Cookbook. It is a compendium of recipes from around Gopherspace. You're receiving this message to let you know that one or more of your recipes has been listed in the cookbook.

The cookbook is available at:
gopher://tellus.strangled.net/1/cookbook

Keep on cooking!
Keep on Gophering!

Feel free to get in touch if you have any queries.

Best,
Rouan aka jandal

--
gopher://grex.org/1/%7ejandal
gopher://tellus.strangled.net/

It's not spam, as the post in question, does have a recipe (if you are having problems with the link, don't worry, that is expected, but in the meantime, you will probably have more luck with this link). The links in question deal with Gopher, a protocol invented at the same time as HTTP, but was soon eclipsed as you couldn't inline cat pictures in a gopher page unlike a webpage. It's mostly dead.

But not all dead.

I'm surprised [No he's not. —Editor] that I haven't mentioned this before [He was being lazy. —Editor], but I set up a server to mainly serve up my blog via gopher: early last March. And if pressed for a reason—it was because I could. I thought it might be fun to have a phlog in addition to a blog.

It's not like it was hard to write the code (alternate link). It just took a day or so for me to get it working, and most of the conversion from HTML to plain text is done by Lynx (which is why it looks the way it looks; alternate link). And I do get the occasional hits on the gopher server, which I find amusing.

And yes, people do still use Gopher.

Wednesday, January 10, 2018

I still find SPF not worth integrating into my email server

The other day, I came across this article about using SPF to avoid large delays using greylisting (link via Lobsters). I've experienced those delays from time to time since I run a greylist daemon and this does seem like a neat idea. But I've already ironed out those large delays (it's been awhile since the last one) so I have very little incentive to implement this.

This did however get me to ask if I should integrate SPF with the greylist daemon.

Then I thought, didn't I already do this?

It turns out I did! Three years ago.

Well … okay then!

Have things changed over the past three years? I spent a few hours over the past few days getting the code up and running, so let's see—over the past month (December 10th to January 10th):

Unique emails processed by the greylist daemon
Emails accepted2,515
Emails rejected2,319
Total 4,834

Aside from the volume (which appears to be a bit less than 50% of what it was three years ago, but that could be due to the time of year), the ratio is similar—50% of the email is spam that is immedately filtered out.

The one major change though, is that back then, around 12½% only had SPF records, whereas today, it's about 12½% don't have SPF records. That's interesting. But the rest of the figures are again, similar to last time:

Results of applying SPF policy against incoming email
fail93IP address was not allowed to send this email
softfail79IP address should not be sending this email (used for testing)
neutral11IP address has no policy
pass962IP address is allowed to send this email

Those with a neutral SPF policy have gone down, and the failure rate is up a bit (4% vs. 1% back then) but the overall conclusion is the same—not worth it.


You know, the ability to comment on-the-fly configuration changes in long running daemons is probably a good idea

And speaking of the greylist daemon, I can filter by IP address:

[spc]brevard:~>gld-mcp show iplist
     30905 GREYLIST         0.0.0.0         0.0.0.0
       115   REJECT  61.175.186.125 255.255.255.255
         0   ACCEPT       64.12.0.0     255.255.0.0
         0   ACCEPT    64.233.160.0   255.255.224.0
         0   ACCEPT     66.94.224.0   255.255.224.0
         0   ACCEPT      66.102.0.0   255.255.240.0
        33   ACCEPT    66.163.160.0   255.255.224.0
         0   ACCEPT     66.218.64.0   255.255.224.0
        81   ACCEPT  66.220.144.128 255.255.255.128
         0   ACCEPT     66.249.80.0   255.255.240.0
         0   ACCEPT     66.249.64.0   255.255.224.0
         0   ACCEPT    66.252.224.0   255.255.252.0
         0   ACCEPT     69.63.184.0 255.255.255.128
         0   ACCEPT     69.63.176.0   255.255.240.0
         0   ACCEPT     69.147.64.0   255.255.192.0
         4   ACCEPT      70.34.16.0   255.255.240.0
         0   ACCEPT     72.14.192.0   255.255.192.0
        16   ACCEPT      74.125.0.0     255.255.0.0
         0   ACCEPT       127.0.0.1 255.255.255.255
      1207   ACCEPT    140.211.11.3 255.255.255.255
         0   ACCEPT     149.174.0.0     255.255.0.0
        12   REJECT     172.128.0.0     255.128.0.0
         7 GREYLIST     173.232.0.0     255.255.0.0
       115 GREYLIST       173.0.0.0       255.0.0.0
         0   ACCEPT     192.168.0.0     255.255.0.0
         0   ACCEPT   204.127.217.0   255.255.255.0
         0   ACCEPT     204.127.0.0     255.255.0.0
         0   ACCEPT    205.152.58.0   255.255.254.0
         0   ACCEPT   205.188.156.0   255.255.254.0
         0   ACCEPT     205.188.0.0     255.255.0.0
         0   REJECT    206.214.64.0   255.255.224.0
         0   ACCEPT    207.115.11.0 255.255.255.192
         0   ACCEPT     207.115.0.0   255.255.192.0
         0   ACCEPT   207.171.188.0   255.255.255.0
       116   ACCEPT    209.85.128.0   255.255.128.0
         0   ACCEPT    209.131.32.0   255.255.224.0
         3   ACCEPT     216.39.48.0   255.255.240.0
         0   ACCEPT    216.239.32.0   255.255.224.0
[spc]brevard:~>

But there's a question I can't answer—why? Why did I accept 69.63.184.0/19? Or 216.39.48.0/20? Heck, I can't even answer when!

What I wish I had done back when I wrote this was allow comments for this filter table. I mean, it's pretty obvious with some of the other filters, such as the to-domain list:

[spc]brevard:~>gld-mcp show to-domain
         0   REJECT area51.conman.org
        75   REJECT linus.area51.conman.org
     30530 GREYLIST DEFAULT
[spc]brevard:~>

The machine linus.area51.conman.org has been decommissioned for over a decade, and yet some spammers somewhere are still attempting to deliver email to it (although it may help if I were to remove the MX and A DNS records for it—hmm …) even after all these years (75 attempts have been attempted since September 6th, 2017 when for whatever reason, the greylist daemon was restarted). It's obvious why I added the line.

But the IP addresses? No idea. The ability to add comments for ad-hoc, on-the-fly updates for long running daemons is something to keep in mind. I just wish I had thought of that sooner.

Monday, January 22, 2018

“It's a movie about food poisoning on an airplane, but that's not important right now.”

Airplane” is one of the funniest movies ever made and it still holds up over 35 years later. Most people think it's a parody of all the airline disaster movies of the 70s, but in reality, it's a remake of a 1957 dramatic movie played straight (which explains why the main character is a World War II fighter pilot in a movie made in 1980).

Sunday, February 11, 2018

“I'm sorry. We can't take your order right now, the computer crashed and we have no idea how to proceed.”

Today is Game Day™. Every other week I get together with some friends to play D&D for a few hours. Sometimes it's hosted here at Chez Boca, other times one of my friend's house. Today it's not at Chez Boca, so as usual, I stop by the Scottish place for a quick lunch. And because I'm weird, I avoid the drive thru.

I noticed a few months ago that McDonald's had installed a few ordering kiosks. Aside from the clunkiness of the interface, it's not that bad. Which upon reflection is strange, because I hate the things at other restaurants. My experience using the Ziosk (not only at the Olive Garden but also Chili's) is not good. A few times the unit has been broken and it took a very confused staff longer to process the check than normal.

And heaven help you if you want to pay by cash.

Cash!

Ha!

So, why do I hate the Ziosks and yet, don't mind the kiosks at McDonald's? I've been thinking about that today, and the best I can come up with is that at a sit-down restaurant, I'm there to enjoy a meal with company and don't want to be distracted by a device not only demanding our attention, but taking up space on a table that can get quite crowded with plates and glasses. I think it also cheapens the waitrons in a way—no longer do you have a single person handling your dinner, but you have several people who cycle through, one person taking the order, one person serving the drinks, another bringing the food, there's not continuity in service. And there's this feeling of replaceability of not only the servers, but of the customers.

And who is the tip for, exactly?

It's hard to describe, and maybe it's just me.

There's also the issue of letting a device, which processes financial transactions into the hands of the customers! Customers which may attempt to hack the devices (although why do I trust the waitrons?). And if the Ziosk crashes … well … I've experienced the chaos it can cause with the staff.

But the kiosk at McDonald's though—there's no tipping. The staff you interact with is just there to take your order. There are other people who do the actual job of preparing your order. And even they don't prepare the entire order. In order to save time we customers are now mostly responsible for filling our own cups of whatever lovely beverage we chose to drink. So that's one job less they have to do. And the kiosks now remove one to two other jobs—taking the order and receiving payment (if you want to pay cash, you have the option to go to the register and pay). So pretty much all that's now left is food preparation.

And I'm fine with that for fast food. Maybe because it's somewhat impersonal to begin with.

All this came to a head today as I was grabing lunch on the way to the D&D game. All the kiosks at The Scottish place had crashed. And there was much confusion at the counter.

Ah, computer automation! Gotta love it.

Monday, February 12, 2018

Tough love, or stultifying ossification? I don't know

There is “Postel's Law” in protocol design that states:

2.10. Robustness Principle

TCP implementations will follow a general principle of robustness: be conservative in what you do, be liberal in what you accept from others.

TRANSMISSION CONTROL PROTOCOL—DARPA INTERNET PROGRAM—PROTOCOL SPECIFICATION

But then there's this:

4.5 Robustness

A well-designed protocol is robust.

Robustness and efficiency are often at odds. For example, although defaults are useful to reduce packet sizes and processing time, they tend to encourage implementation errors.

Counter-intuitively, Postel's robustness principle ("be conservative in what you send, liberal in what you accept") often leads to deployment problems. Why? When a new implementation is initially fielded, it is likely that it will encounter only a subset of existing implementations. If those implementations follow the robustness principle, then errors in the new implementation will likely go undetected. The new implementation then sees some, but not widespread deployment. This process repeats for several new implementations. Eventually, the not-quite-correct implementations run into other implementations that are less liberal than the initial set of implementations. The reader should be able to figure out what happens next.

Accordingly, explicit consistency checks in a protocol are very useful, even if they impose implementation overhead.

On the Design of Application Protocols

I bring this up because I recently came across this:

… The first byte of the clear data was a flags field which, he said, was promptly ossified by a middlebox vendor, leading to packets being dropped when a new flag was set.

That was a classic example of why changing network protocols is hard and what needs to be done to improve the situation. Middleboxes are the control points for the Internet as we know it now. The only defense against ossification of network protocols by middleboxes, he said at the conclusion of the talk, is encryption.

Via Hacker News, QUIC as a solution to protocol ossification [LWN.net]

And I thought, Oh crap! I do that!

More specifically, in SPCDNS where I explicitly check for unused bits being zero.

Am I ossifying the DNS protocol by doing this?

I did encounter this a few months ago. I was playing around with monitoring the traffic on the home network and saw a bunch of MDNS requests flying around. I thought I would decode them using SPCDNS to see what exactly was being queried when I hit a snag—some of the packets were invalid! Upon investigation, it came down to that single undefined bit in the DNS packet being set. I quickly patched the code (privately) to accept the packets but I didn't release the changes since at the time, that last undefined bit was still undefined.

I didn't know how to deal with the situation then, and I still don't. SPCDNS can handle records it doesn't understand, but that one undefined bit has me stymied. I could define the flag and let a user of my code check for it, but when it does become defined, that flag name will obviously have to change and that could be a breaking change. But as of right now, any user code that wants to check for that bit has no way of doing so (not that I've received any requests for it).

Then there's the fact that because my code was so fussy with verifying the packet, that bugs in other DNS implementations were found via my code. And at work, I put up a fight to remain picky in processing network packets for “Project: Sippy-Cup.” I mean, what's the point of a protocol specification if you don't follow it? I even referenced RFC-3177 (quoted above) as part of my argument for being picky. But I was overridden and had to carry on in the face of utter garbage (and yes, some of what we get is utter garbage). I did however keep track of each violation and we are in the process of talking with a vendor who is sending us garbage as I type.

This is tough.

At the time I wrote SPCDNS, there was only one undefined bit left in the DNS packet. Had I written it back when RFC-1035 was written, there would have been three undefined bits, and I ask myself how I would have handled that over the years. I'm not even sure if I would have thought to include those bits in what is decoded (I don't now).

This will require some thought.


Tortoise and hare racing

I never expected this to be a thing, but tortoise vs. hare, tortoise vs. hare and tortoise vs. hare. And each time, the result is the same.

No, really.

Wednesday, February 14, 2018

Again, it was quite crowded out tonight. What is it with February 14th and everybody eating out? I'm wondering if it's some sort of holiday

As we did last year, Bunny and I had a wonderful dinner at Roots Italian Kitchen, only this time, we were able to skip the whole non-Euclidean parking garage for the Biltmore that for some reason lurks here in downtown Boca Raton. Once you know where to look, it's easily skipped.

We walked inside and Yuriy (the owner of the restaurant with an incredible memory) greeted us warmly and thanked us for coming back and dining with his establishment on St. Valentine's Day.

[This place is so fancy, even the tables are garnished!]

We were shown to our table, which was decorated with rose petals. Every table was decorated with rose petals. It was an interesting touch I had never seen before.

[Why yes, I'm still trying to destroy the cliché that is a full plate of beautiful food by making my own cliché of an empty plate for formerly beautiful food.]

The appetizer was okay.

Okay, who am I kidding? It was an incredible lobster-and-crabcake appetizer that was easily the best part of the entire meal. That's not to say the rest of the meal was bad—it wasn't. The Chicken Bella Risotto (grilled portobellos with chicken in a creamy risotto) was wonderful (we both had it) and dessert was worth the wait (Tiramisu for Bunny, and a brownie á la mode sans mode for me; sadly, the only misstep of the meal was the restaurant running out of vanilla ice cream, but still, that brownie was good).

But that lobster-and-crabcake appetizer … wow!

It was a good thing we parked a few blocks away (to avoid that non-Euclidean garage lurking in downtown Boca Raton)—we could use the walk after a meal like that.

Monday, February 19, 2018

Fun with banging moon rocks

Back in Debtember, I was notified of a potential problem with one of my Lua modules, speficically, the LuaRocks specfile of said module—it failed to compile properly on Mac OS-X.

I finally got around to it and fixed the issue, and while I was doing that, I figured I might as well fix some of the other Lua modules I have.

You can always tell when I do this because the version numbers accumulate in a rapid succession. My CBOR Lua module went from version 1.2.4 to 1.2.11 in the span of an hour or so. And it's all due to the picky little details.

As I mentioned a few months ago, I pull the version directly from git. But I also have to define the version in the Makefile in case someone downloads the code instead of cloning the repository. But there have been times when I updated the GitHub repository without updating the Makefile, or forgot to properly rename the LuaRocks specfile (probably as a sanity check, the filename needs to include the version number which is also specified inside the file). To handle those cases, I added a script to git to check for such things before pushing the update to GitHub.

So it should be easy, right?

Not quite.

One issue I forgot to check in the script was to ensure the LuaRocks specfile was syntactically correct. So there goes one version.

The Lua module is written with C99. So I specified c99 as the compiler in the LuaRocks specfile. Only the default options LuaRocks uses breaks on Mac OS-X with c99 as the compiler. The why is simple—Mac OS-X uses clang, which supports different options than GCC. But LuaRocks defaults to using GCC when compiling on Mac OS-X. That's fine, because there's a GCC wrapper on Mac OS-X that translates the options for GCC to clang, but only if the compiler you use is GCC. On Mac OS-X, c99 defaults to clang so of course it fails because clang receives options for GCC.

I can use the default compiler that LuaRocks defines on Mac OS-X and it compiles fine. But not on Linux, where GCC defaults to “not C99.” I finally figured out the magical incantation to fix that:

build =
{
  platforms =
  {
    windows =
    {
      type    = "builtin",
      modules = 
      {
        ['org.conman.cbor_c'] = 
        {
          sources = { 'cbor_c.c', 'dnf.c' },
          defines = { 'VERSION="' .. source.tag .. '"' },
        },

        ['org.conman.cbor']     = 'cbor.lua',
        ['org.conman.cbor_s']   = 'cbor_s.lua',
        ['org.conman.cbormisc'] = 'cbormisc.lua',
      }
    }
  },
  
  type = "make",
  build_variables =
  {
    CC      = "$(CC)",
    CFLAGS  = "$(CFLAGS) -DNDEBUG -I$(LUA_INCDIR)",
    LDFLAGS = "$(LIBFLAG)",
    LUA     = "$(LUA)",
  },
  
  install_variables =
  {
    LIBDIR = "$(LIBDIR)",
    LUADIR = "$(LUADIR)",
    LUA    = "$(LUA)",
  },
  
  platforms =
  {
    linux   = { build_variables = { CC = "gcc -std=c99" } },
    solaris = { build_varaibles = { CC = "c99"          } },
  }
}

And it worked fine. But it burned through some additional versions as I worked out the details. And then I found an issue—if you look closely, you'll notice that I have the patforms stanza twice. That means the second stanza replaces the first stanza and thus, I lost the Microsoft Windows compiling instructions.

So yet another version goes by as I merge the two platforms stanzas into a single block.

And then I forgot to update the version number in the LuaRocks specfile. It had the right name, but the wrong internal version.

So there's another version and an update the the checking script.

By now, you might be wondering why I don't bother testing this before updating the version number. And it's simple—I can't! The LuaRocks specfile contains this bit:

package = "org.conman.cbor"
version = "1.2.11-1"

source =
{
  url = "git://github.com/spc476/CBOR.git",
  tag = version:match "[^-]+"
}

To test it, LuaRocks will download the code from GitHub using the given tag value, which is based off the version number. But if I haven't checked in the code for that tag, LuaRocks will fail. So I have to check in the code with the proper tag before I can test the LuaRocks file.

Yes, I could do the code updates and afterwards fix the LuaRocks specfile, but the script that's run prior to pushing changes checks to see if the latest version is a “good version,” like 1.2.10. It will reject a version like 1.2.10-1-g5b75b4f (which is git's way of saying “one commit past the previous tagged version”). I added that check to ensure LuaRocks would get the proper version of everything—I would only push when I had everything ready for a new version.

Ah—unintended consequences.

We'll see if the next update goes smoother. One of these days I'll get this right.


Why one might want to load dynamic objects from memory instead of from disk

Years ago I started on a little project entitled the LEM Project. It was a project to make distribution of applications written in Lua easier (It's named after the Apollo Lunar Moduleaka the Lunar Excursion Module; Lua is “moon” in Portuguese). I had a few goals:

  1. allow distribution of multiple versions of a Lua module;
  2. allow for different architectures for the same module written in C;
  3. run the entire application from the distribution file (nothing to install).

And I almost hit all the goals.

The first two were easy. I read over the ZIP file specification and saw that

  1. multiple files of the same name were entirely possible—nothing in the specification disallows it;
  2. additional metadata can be added to each file beyond what is defined in the specification.

So armed, I created zip file with some addtional metadata and …

[spc]lucy:~/projects/LEM>./zipf.lua sample.lem
The Eagle Has Landed
SunOS     sparcv9   LGPL3+       Lua 5.1 5.1        MODULES/org.conman.base64
SunOS     sparcv9   LGPL3+       Lua 5.1 5.1        MODULES/org.conman.crc
SunOS     sparcv9   LGPL3+       Lua 5.1 5.1 5.1    MODULES/org.conman.env
SunOS     sparcv9   LGPL3+       Lua 5.1 5.1 5.1    MODULES/org.conman.errno
SunOS     sparcv9   LGPL3+       Lua 5.1 5.1        MODULES/org.conman.fsys
SunOS     sparcv9   LGPL3+       Lua 5.1 5.1        MODULES/org.conman.hash
SunOS     sparcv9   LGPL3+       Lua 5.1 5.1 1.1    MODULES/org.conman.iconv
SunOS     sparcv9   LGPL3+       Lua 5.1 5.1 5.1    MODULES/org.conman.math
SunOS     sparcv9   LGPL3+       Lua 5.1 5.1        MODULES/org.conman.net
SunOS     sparcv9   LGPL3+       Lua 5.1 5.1        MODULES/org.conman.pollset
SunOS     sparcv9   LGPL3+       Lua 5.1 5.1        MODULES/org.conman.process
SunOS     sparcv9   LGPL3+       Lua 5.1 5.1        MODULES/org.conman.strcore
SunOS     sparcv9   LGPL3+       Lua 5.1 5.1 1.0.0  MODULES/org.conman.sys
SunOS     sparcv9   LGPL3+       Lua 5.1 5.1 5.1    MODULES/org.conman.syslog
Linux     x86       LGPL3+       Lua 5.1 5.1        MODULES/org.conman.base64
Linux     x86       LGPL3+       Lua 5.1 5.1        MODULES/org.conman.crc
Linux     x86       LGPL3+       Lua 5.1 5.1 1.0.0  MODULES/org.conman.env
Linux     x86       LGPL3+       Lua 5.1 5.1 1.0.0  MODULES/org.conman.errno
Linux     x86       LGPL3+       Lua 5.1 5.1        MODULES/org.conman.fsys
Linux     x86       LGPL3+       Lua 5.1 5.1        MODULES/org.conman.fsys.magic
Linux     x86       LGPL3+       Lua 5.1 5.1        MODULES/org.conman.hash
Linux     x86       LGPL3+       Lua 5.1 5.1 1.1.1  MODULES/org.conman.iconv
Linux     x86       LGPL3+       Lua 5.1 5.1 5.1    MODULES/org.conman.math
Linux     x86       LGPL3+       Lua 5.1 5.1        MODULES/org.conman.net
Linux     x86       LGPL3+       Lua 5.1 5.1        MODULES/org.conman.net.ipacl
Linux     x86       LGPL3+       Lua 5.1 5.1        MODULES/org.conman.pollset
Linux     x86       LGPL3+       Lua 5.1 5.1        MODULES/org.conman.process
Linux     x86       LGPL3+       Lua 5.1 5.1        MODULES/org.conman.strcore
Linux     x86       LGPL3+       Lua 5.1 5.1 1.2.0  MODULES/org.conman.sys
Linux     x86       LGPL3+       Lua 5.1 5.1 1.0.2  MODULES/org.conman.syslog
Linux     x86       LGPL3+       Lua 5.1 5.1        MODULES/org.conman.tcc
                    LGPL3+       Lua 5.1 5.1        MODULES/org.conman.cc
                    LGPL3+       Lua 5.1 5.1        MODULES/org.conman.date
                    LGPL3+       Lua 5.1 5.1        MODULES/org.conman.debug
                    LGPL3+       Lua 5.1 5.1        MODULES/org.conman.dns.resolv
                    LGPL3+       Lua 5.1 5.1        MODULES/org.conman.getopt
                    LGPL3+       Lua 5.1 5.1        MODULES/org.conman.string
                    LGPL3+       Lua 5.1 5.1        MODULES/org.conman.table
                    LGPL3+       Lua 5.1 5.1        MODULES/org.conman.unix
                    MIT          Lua 5.1 5.1 0.10   MODULES/lpeg
                    MIT          Lua 5.1 5.1 0.10   MODULES/re
Linux     x86       MIT          Lua 5.1 5.1 0.12   MODULES/lpeg
Linux     x86       MIT          Lua 5.2 5.2 0.12   MODULES/lpeg
                    MIT          Lua 5.1 5.2 0.12   MODULES/re
Linux     x86       MIT/X11      Lua 5.1 5.1 0.4.work3 MODULES/zlib
                    MIT/X11      Lua 5.1 5.1 2.0.2  MODULES/socket
Linux     x86       MIT/X11      Lua 5.1 5.1 2.0.2  MODULES/socket.core
                    MIT/X11      Lua 5.1 5.1 2.0.2  MODULES/socket.ftp
                    MIT/X11      Lua 5.1 5.1 2.0.2  MODULES/socket.http
                    MIT/X11      Lua 5.1 5.1 2.0.2  MODULES/socket.smtp
                    MIT/X11      Lua 5.1 5.1 2.0.2  MODULES/socket.tp
                    MIT/X11      Lua 5.1 5.1 2.0.2  MODULES/socket.url
                    MIT/X11      Lua 5.1 5.1 1.0.1  MODULES/ltn12
                                                    FILES/APPNOTE.TXT
                                                    FILES/COPYING
                                                    FILES/README
                                                    FILES/Miscellaneous Things About Nothing
[spc]lucy:~/projects/LEM>

You can see there are several copies of each module. The modules listed without a system (like Linux or SunOS) are written in Lua; the other ones are in C and both the system and architecture are listed. The license is included, along with the Lua verions the module will work for (it's “minimum version” and “maximum version”) as well as the version of the module (if known).

It's even a valid zip file:

[spc]lucy:~/projects/LEM>unzip -l sample.lem
Archive:  sample.lem
The Eagle Has Landed
  Length     Date   Time    Name
 --------    ----   ----    ----
    25472  05-24-14 17:10   MODULES/org.conman.base64
    13448  05-24-14 17:10   MODULES/org.conman.crc
    12200  05-24-14 17:10   MODULES/org.conman.env
    18688  05-24-14 17:10   MODULES/org.conman.errno
    57032  05-24-14 17:10   MODULES/org.conman.fsys
    24952  05-24-14 17:10   MODULES/org.conman.hash
    17664  05-24-14 17:10   MODULES/org.conman.iconv
    17648  05-24-14 17:10   MODULES/org.conman.math
    77944  05-24-14 17:10   MODULES/org.conman.net
    26296  05-24-14 17:10   MODULES/org.conman.pollset
    88256  05-24-14 17:10   MODULES/org.conman.process
    37848  05-24-14 17:10   MODULES/org.conman.strcore
    15392  05-24-14 17:10   MODULES/org.conman.sys
    24312  05-24-14 17:10   MODULES/org.conman.syslog
    14175  06-12-14 22:04   MODULES/org.conman.base64
     8214  06-12-14 22:04   MODULES/org.conman.crc
     7193  06-12-14 22:04   MODULES/org.conman.env
    10690  06-12-14 22:04   MODULES/org.conman.errno
    31885  06-12-14 22:04   MODULES/org.conman.fsys
    15567  06-12-14 22:04   MODULES/org.conman.fsys.magic
    14067  06-12-14 22:04   MODULES/org.conman.hash
    10197  06-12-14 22:04   MODULES/org.conman.iconv
    10816  06-12-14 22:04   MODULES/org.conman.math
    43651  06-12-14 22:04   MODULES/org.conman.net
    25248  04-18-14 20:06   MODULES/org.conman.net.ipacl
    15914  06-12-14 22:04   MODULES/org.conman.pollset
    49607  06-12-14 22:04   MODULES/org.conman.process
    15666  06-12-14 22:04   MODULES/org.conman.strcore
     9763  06-12-14 22:04   MODULES/org.conman.sys
    13303  06-12-14 22:04   MODULES/org.conman.syslog
    21218  06-12-14 22:04   MODULES/org.conman.tcc
     5617  06-12-14 22:04   MODULES/org.conman.cc
     2500  06-12-14 22:04   MODULES/org.conman.date
     3829  06-12-14 22:04   MODULES/org.conman.debug
     2966  06-12-14 22:04   MODULES/org.conman.dns.resolv
     3260  06-12-14 22:04   MODULES/org.conman.getopt
     2464  06-12-14 22:04   MODULES/org.conman.string
     5243  06-12-14 22:04   MODULES/org.conman.table
     2732  06-12-14 22:04   MODULES/org.conman.unix
    40081  05-25-14 15:17   MODULES/lpeg
     6029  05-24-14 00:36   MODULES/re
    40045  05-28-14 15:24   MODULES/lpeg
    40045  05-28-14 15:24   MODULES/lpeg
     6286  05-28-14 15:24   MODULES/re
    19794  05-30-14 21:29   MODULES/zlib
     4451  05-28-14 14:52   MODULES/socket
    55449  05-28-14 14:52   MODULES/socket.core
     9243  05-28-14 14:52   MODULES/socket.ftp
    12330  05-28-14 14:52   MODULES/socket.http
     8074  05-28-14 14:52   MODULES/socket.smtp
     3612  05-28-14 14:52   MODULES/socket.tp
    11036  05-28-14 14:52   MODULES/socket.url
     8331  05-28-14 14:52   MODULES/ltn12
   161412  05-09-14 01:24   FILES/APPNOTE.TXT
The ZIP file format
     7651  05-25-14 18:53   FILES/COPYING
     9789  06-07-14 22:13   FILES/README
Much Ado About Nothing
     3946  05-10-99 23:00   FILES/Miscellaneous Things About Nothing
If you this this has significance, think otherwise
 --------                   -------
  1250541                   57 files
[spc]lucy:~/projects/LEM>

(Although if you try to unzip this file, the unzip program will ask you what you want to do with the duplicate files.)

The intent was that only those modules that match the Lua version, system (if a C-based Lua module) and architecture (again, C-base Lua module) match, load the module; otherwise, it would be ignored.

And it worked. For the most part.

I could load Lua modules written in Lua directly from the zip file with no problem. I even got LuaRocks to run completely from the zip file (with some hacks so it could load the configuration file). But I could not do that for the C-based Lua modules. For those, you had to write them out to disk to load them up. And because of that, I lost interest in continuing the project.

Until now. I just came across MojoELF (via Project: 2ine which was linked via Hacker News)—a project to load ELF binaries directly from memory (and those C-based Lua modules I have are ELF binaries), which is exactly what I wanted all those years ago.

Wednesday, February 28, 2018

Notes on an overheard conversation while driving south along I-95

“When are they going to finish all this contruction? The road here is terrible!”

“It keeps the drivers on their toes.”

“The lanes are all uneven! It could force you into the next lane!”

“Yes, that's what makes it exciting.”


A potential way to have spaces in filenames and not break the Unix command line

A thread at Hacker News about using makefiles for JavasScript was about the difficulty in using filenames with spaces. And yes, it is difficult. A Makefile such as:

hello world:

Results in:

[spc]lucy:/tmp/foo>make
make: Nothing to be done for `hello'.
[spc]lucy:/tmp/foo>

Enclosing the filename with quotes (single or double, it doesn't matter) gives the same results. If I escape the space like:

hello\ world:

make gives:

[spc]lucy:/tmp/foo>make
cc     hello world.c   -o hello world
cc: hello: No such file or directory
cc: world.c: No such file or directory
cc: world: No such file or directory
cc: no input files
make: *** [hello world] Error 1
[spc]lucy:/tmp/foo>

So yes, using a filename with spaces is problematic with make. Part of that is the unique nature of the space character. In ASCII, it's grouped next to the information separator characters and thus, could be treated as another type of separator character (and on input, it usually is considered such). It could also be considered a control character as a format effector such that it causes the character position to advance one place to the right (and is thus used as such with output).

It's the prevasive use of space as a separator in Unix that causes the most issues, such with make, and the command line in general.

But there is a solution …

[spc]lucy:/tmp/foo>ll
total 12
-rw-r–r–  1 spc spc  14 Feb 28 18:13 Makefile
-rw-r–r–  1 spc spc  76 Feb 28 18:13 hello world.c
-rw-r–r–  1 spc spc 227 Feb 28 18:13 x.lua
[spc]lucy:/tmp/foo>cat Makefile
hello world:
[spc]lucy:/tmp/foo>make
cc     hello world.c   -o hello world
[spc]lucy:/tmp/foo>./hello world
Hello, world!
[spc]lucy:/tmp/foo>

No, the output is not faked. Yes, the filename is hello world.c. The name, however, is not pure ASCII—it contains the Unicode character for a “non-breaking space”. Cheating? Perhaps. But it is defined as a space (graphically), and more importantly, it's not considered an information separator by Unix utilties. It also requires a filesystem that can support Unicode (or in my case, UTF-8) and a command line that also supports Unicode (or again in my case, UTF-8). And it was also not that easy to create the filename and Makefile with the non-breaking space.

But other than those minor issues [Ha! —Editor], hey—spaces! In filenames!

Saturday, March 03, 2018

Yak Shaving

I hate yak shaving.

I made a small fix to mod_blog, and when I went to update the copy on GitHub, it failed. All I got back was: “no kex alg.”

Ah, an error message from the Ken Thompson School of Error Messages.

Analyzing the tea leaves, it seems my version of openssl was, shall we say, a bit older than 20 minutes? And something happened at GitHub to precipitate the change. What, I could not say (perhaps?).

So, to get back to where I was a few days ago:

  1. Download the latest version of openssl.
  2. Run the configuration script, only to find out my version of Perl was too old.
  3. Download latest version of Perl.
  4. Configure Perl.
  5. Attempt to make Perl.
  6. Track down error message from compiling Perl.
  7. Reconfigure Perl, this time to use C99 when compiling.
  8. Attempt to make Perl. Success!
  9. Hmm … make tests? Sure, why not?
  10. Wait a bazillion hours while the tests run.
  11. See that five tests out of 3000+ failed.
  12. Figure that's close enough for government work, and install Perl anyway.
  13. Reconfigure openssl.
  14. Make openssl.
  15. Install openssl.
  16. Recompile a program I wrote that uses openssl.
  17. Get confused as to why it's not linking to openssl yet it still works.
  18. Find several previous attempts to install openssl and decide to remove them.
  19. Then suddenly realize that I was too hasty and that bind will no longer start.
  20. Add recompile of bind to list of taks I need to do.
  21. Figure out my program is being statically linked to a previous version of openssl.
  22. Put that problem aside. Download latest version of openssh.
  23. Configure openssh, only to find it doesn't support the latest version of openssl.
  24. Unisntall latest version of openssl.
  25. Download latest previous version of openssl.
  26. Configure latest previous version of openssl.
  27. Make openssl.
  28. Install openssl.
  29. My program is still being statically compiled to older version of openssl.
  30. Force the issue—it fails to link.
  31. Realize that the latest previous version of openssl installed in /usr/local/ssl instead of /usr/local.
  32. Reconfigure latest previous version of openssl to install in /usr/local.
  33. Make openssl.
  34. Install openssl.
  35. Try linking my program again.
  36. Find out that by default, openssl only generates a static library.
  37. Reconfigure openssl to generate dynamic libraries.
  38. Make openssl.
  39. Install openssl.
  40. Get my program to dynamically link to /usr/local/lib/libcrypto.so, although I'm still forcing that.
  41. Configure openssh. This time it works.
  42. Make openssh.
  43. Install openssl.
  44. Run ssh -T git@github.com. It works!
  45. Carefully compare previous configuration for sshd to new version of sshd.
  46. Carefully tweak new configuration of sshd.
  47. Copy server keys so new configuration can see them.
  48. Test new sshd. It works.
  49. Update start up script to run new sshd.
  50. Realize I have to recompile git to use the updated openssl.
  51. Clean out previous object files in my local copy of git.
  52. Make git.
  53. Install git.
  54. Done!
  55. No, wait … there was something … what was it?
  56. Oh, right! bind!
  57. Clean out previous object files in my local copy of bind.
  58. Make bind.
  59. Stop current version of bind.
  60. Install new bind.
  61. Start up new version of bind.
  62. Start breathing again when it works.
  63. Decided to remove the old openssl static library; now programs will dynamically link to the latest previous version of openssl.
  64. Done!

Now I can update my repository on Github!

I realize that I bring this upon myself by avoiding the whole “upgrade every 20 minutes” schtick, but I believe in the “if it ain't broke, don't fix it” mentality and that the computer is here for my needs, I'm not here for the computer's needs.

Besides, the last time I indiscriminately upgraded, it did not go well

Tuesday, March 06, 2018

The Revenge of the Hamless Ham and Cheese without the Cheese

“What would you like?”

“I'll take a ham and cheese, please.”

“Type of bread?”

“White.”

“Mayo?”

“Yes.”

“Do you want cheese?”

Seriously? This is still happening eighteen years later?

Sunday, March 11, 2018

It's almost as if they use a template or something when sending the emails

So I'm checking my email when I see this:

From
Jesse Miller <XXXXXXXXXXXXXXXXXXXXXX>
To
sean@conman.org
Subject
Research on Things to do in Vegas
Date
Sun, 11 Mar 2018 07:51:12 -0400

Dear Editor,

My name is Jesse and I’m a writer at Jen Reviews. I was doing research on things to do in Vegas and just finished reading your wonderful post: http://boston.conman.org/2006/07/19.1

In that article, I noticed that you cited a solid post that I’ve read in the past: http://www.wynnlasvegas.com/

I just finished writing a guide that is even more detailed, updated and comprehensive on the 100 best things to do in Vegas. It is over 7,500 words, packed with practical tips and advice, and completely free. You can find it here: https://www.jenreviews.com/best-things-to-do-in-las-vegas/

If you like the guide we’d be humbled if you cited us in your article. Of course, we will also share your article with our 50k newsletter subscribers and followers across our social platforms.

Either way, keep up the great work!

Warmly,
Jesse

And I didn't know how to respond. I mean, I should probably not respond, as “Jesse” probably did not read the post in question, but I was tempted to reply with:

From
Sean Conner <sean@conman.org>
To
Jesse Miller <XXXXXXXXXXXXXXXXXXXXXX>
Subject
Re: Research on Things to do in Vegas
Date
Sun, 11 Mar 2018 21:22:00 -0400

Of course you can share my post with your 50k newsletter subscribers! Not many people have experienced the dread terror that comes with a dark and silent casino filled with nothing but slot zombies, although any Disney and/or Wynn employees that might be part of your subscriber base might have an issue with the phrase “Disneyfication of European elegance of the Wynn.”

Not quite so sincerely yours,
Sean

But then I saw this email:

From
Jen Miller <XXXXXXXXXXXXXXXXXXXX>
To
root@conman.org
Subject
Research on Things to do in Vegas
Date
Sun, 11 Mar 2018 08:32:46 -0400

Dear Editor,

My name is Jen and I’m a writer at Jen Reviews. I was doing research on things to do in Vegas and just finished reading your wonderful post: http://boston.conman.org/2010/01/15.1

In that article, I noticed that you cited a solid post that I’ve read in the past: http://www.visitlasvegas.com/

I just finished writing a guide that is even more detailed, updated and comprehensive on the 100 best things to do in Vegas. It is over 7,500 words, packed with practical tips and advice, and completely free. You can find it here: https://www.jenreviews.com/best-things-to-do-in-las-vegas/

If you like the guide we’d be humbled if you cited us in your article. Of course, we will also share your article with our 50k newsletter subscribers and followers across our social platforms.

Either way, keep up the great work!

Warmly,
Jen

And now I know that “Jen Reviews” never read either post. Because this second post has nothing at all to do with Lost Wages other than a throwaway link (that I had to find) near the bottom of the post.

I am shocked! Shocked, I say, to realize they're just spamming every site that links to anything linking to Lost Wages.

Update on Monday, March 19th, 2018

“Jesse” wrote back, asking for my thoughts on the original email. So that reply that I was tempted to use?

I used it.

Update a few moments later …

“Jen” also asked for an update. I sent “Jen” the same reply.

Monday, March 19, 2018

This won't help, but it provided just a tab bit of enjoyment

Sigh.

The spam. It does not stop.

I received a followup message from both “Jesse” and “Jen”, and now this:

From
Michelle Barlow <XXXXXXXXXXXXXXXXXXXXXXXXXXX>
To
sean@conman.org
Subject
RE:
Date
Mon, 19 Mar 2018 12:32:51 +0000

Hi there,

I came across your site while looking for resources for our next blog and I knew I had to reach out immediately, kudos on a fantastic blog. My name is Michelle, and I'm reaching out on behalf a online gambling company. This month, we're looking to secure sponsorship placements with five prominent blogs and your site jumped straight to the top of our list. Please let me know if this is something you're interested in discussing further.

Kind regards,
Michelle

If I'm going to receive this crap, I might as well have fun. I replied to both “Jesse” and “Jen” with the reply I was tempted to reply with (let's see how they handle that) and to “Michelle” I replied thusly:

From
Sean Conner <sean@conman.org>
To
Michelle Barlow <XXXXXXXXXXXXXXXXXXXXXXXXXXX>
Subject
Re:
Date
Mon, 19 Mar 2018 19:16:45 -0400

It was thus said that the Great Michelle Barlow once stated:

Hi there,

I came across your site while looking for resources for our next blog and I knew I had to reach out immediately, kudos on a fantastic blog. My name is Michelle, and I'm reaching out on behalf a online gambling company. This month, we're looking to secure sponsorship placements with five prominent blogs and your site jumped straight to the top of our list. Please let me know if this is something you're interested in discussing further.

Thank you so much for the flashbacks I'm now experiencing. I live in Florida, and back in 2004, I was working with a gentleman who ran marketing for a gambling web site in Costa Rica. Between Hurricane Frances and Hurricane Ivan our site (as well as my private server which had no relation to the gambling marketing sites) was hacked and completely wiped out by the Russian Mob as part of an extortion racket.

I … I thought I was over it … but …

For background, yes, I was hacked between hurricanes (as part of an inside job). I can't say for certain if it was the Russian Mob, but hey, it makes it a bit more exciting.

Friday, March 23, 2018

Москва в Бока-Ратоне

Bunny and I are sitting on the patio of Biergarten Boca Raton, listening to the live musicians as they finish playing “Starway to Heaven” and segue into “Knocking on Heaven's Door” when I spot a nearby restaurant called “Mantana.” A weird name, “Mantana.” I have to look it up and see what type of restaurant it is—

 (561) 757-3504 Проложить маршрут

MANTANA Gastro Lounge

Кафе (Boca Raton)

Откроется завтра в 8:00

Вызвать (561) 757-3504

Обновления

—and it's Russian!

Or rather, in Russian. I'm not surprised at a Russian restaurant; we have restaurants from all over down here in Lower Sheol. And it might (maybe) be fun to try it, as I'm not terribly familiar with Russian cuisine outside of borscht and stroganoff (is that even Russian? I don't know).

But the text—Russian text!

I can't even find a link to the menu to see what's on it.

I could call, and while I can use Google translate to ask “Какую пищу вы обслуживаете?” I'm not sure I could pronounce it!

Saturday, March 24, 2018

My Facebook Dossier—now you too can get yours

I came across this tweet:

Download your Facebook account .zip off their site, unzip it, then go to the HTML folder, open the contact_info.htm file. See records of who you've talked to on your cell?not with the app, just on your regular cellphone?and for how long.

Via Hacker News, Mat Johnson on Twitter

I'm curious. So let me download this .zip file from Facebook and see what they have on me (the link to download said file is on the “General Account Settings” page, shown as “Settings” from a pull-down menu masquerading as an upsidedown triangle in the upper right corner of a Facebook page). A few minutes later, Facebook notified that my .zip file was ready for download.

I'm happy to say that the contact_info.htm file is empty! Apparently, Facebook has a hard time obtaining such information from iPhone users (I only had the app installed for maybe a month years ago and ended up deleting it). Android users who have the Facebook app installed will probably be surprised to find what's there.

The timeline.htm file shows every post (but no comments!) I've made. My first entry reads “is trying to figure out the hype around MyFaceSpaceBook” from November 11th, 2008. And my first blog entry I posed was this one two days later. There are also copies of every picture I posted, along with any comments they received (nice). Interestingly, each picture also comes with additional information:

Since most cameras include such information in each picture (except for the upload IP address) it's not surprising to see Facebook using it. But as I know that most cameras include such information, I have always stripped it out before uploading the images (it doesn't matter where—whether to my own blog or to MyFaceGoogleLinkedInSpace­ BookPlus) there's nothing there, except for the IP address.

There's a list of all the people I've “friended,” along with a list of requests I've sent that haven't been accepted. I see that Bobby Cannavale has yet to accept my “friend“ request I sent on November 28th, 2008 (come on Bobby! We were in a play together in high school! You remember that, don't you?). There's also a list of “friends” I've declined to accept (Sorry Ken Lee, but you left me hanging! No way I'm going to “friend” you now).

The scariest information I've found was in the ads.htm file:

Advertisers with your contact info

Thank you for informing me that Viking Ocean Cruises have my contact information, but why did I not get a cut of the action here, Facebook? You certainly earned some money selling that information to Inrego AB, but I too, would like some of that filthy, filthy lucre. Oh wait … you aren't letting me use Facebook without charge out of the goodness of your heart—I'm “paying” for Facebook with information about me. Okay, I get it. I'm the product being sold.

There's a bunch more information but it's stuff I have given to Facebook so it's not terribly surprising.

So that's what Facebook is willing to tell me about what they have on me. I'm sure they have way more on me that I'm not privy to, like what sites they have tracked me visiting, what I'm worth to them, and what they think I like and dislike, what my political affilation is, and if I'm one of the 50 million users whose information was ultimately sold to the Trump campaign, or if I'm one of the 180 million users whose information was ultimately sold to the Obama campaigns.

I'm not holding my breath on getting that information.

Sunday, April 01, 2018

“You guys thought I was dead? Ha ha! April Fools!”

[This is the colorful Osterhase which brings forth a bounty of colorful eggs, not to be confused with the golden brown Hasenpfeffer, which is brought forth with onions and a marinade of wine and vinegar.]

At Chez Boca, the Easter Bunny is as colorful as the eggs.

Wednesday, April 04, 2018

A few days to change what amounts to about three lines of code

I spent a few days tracking down a tough bug in “Project: Sippy-Cup”. The bug wasn't in the happy path (explained here) but the “unhappy path” that happens when a timeout occurs [memo to self: check the blog before spending a few hours rewriting what you previously wrote].

We were able to reproduce the error rather quickly. What took the time was trying to isolate the root cause, and what I should have done [memo to self: reread my previous memo to self] was enable the statement logging I did a few years ago. Doing so allowed me to find the root rather quickly.

Each request is handled in a coroutine (think “very cheap thread”). The coroutine will acknowledge the incoming SIP message, extract the data we need from said message and send it to the “Business Logic Unit.” But because we have a limited amount of time to do that voodoo that we do (else we exceed our SLA and have to pay large amounts of money to The Monopolistic Phone Company), we will only wait for a limited period of time for the reply from the “Business Logic Unit.” In either case, we then send out a SIP message and wait for an acknowledgement that it was received.

The happy path—nothing times out and everybody is happy. The unhappy path is when the reply from the “Business Logic Unit” is late, and that late reply was somehow showing up as the “acknowledgement,” which my code didn't handle gracefully at all!

So normally the program does:

And the unhappy path was supposed to go like:

So really, not much difference. But in reality things were different:

The fix, as always, was easy—if a coroutine is scheduled to run, don't reschedule it. What's not so easy is finding the root cause.

Tuesday, May 29, 2018

Non-web protocols are dead! All Hail HTTPS!

So I came across this blog post about DNS over HTTPS and …

… yeah …

… I feel that this is it. The Internet has ossified. There are no new programs or protocols—it's either on the web, or it doesn't exist.

Last week it came down from On High™ that both “Project: Wolowizard” and “Project: Sippy-Cup” will be making REST calls, most likely over TLS, rather than the current method of DNS (on a private network).

Because … reasons.

The company we query for data has drunk the REST/HTTPS über alles Kool-Aid™ and we get to suffer. We now get to make expensive network queries during the establishment of a phone call. We've been told not to worry, some load testing will be done, but hey, it's all good. It'll be HTTP/1.1.

For now.

Maybe HTTP/2.0 (which is nothing more than TCP over TCP over TLS if Google has their way, and it appears they are). But definitely HTTP/1.1 for now.

Oh, and the data we'll get back is in JSON.

Of course it is.

Lovely.

Damn hipster developers! Get off my lawn!

Wednesday, May 30, 2018

Why yes, programmers always wear mirror shades while programming—it's part of Programming 101

From my friend Brian Yoder on My­Face­Google­Linked­In­Space­Book­Plus is this cute video contrasting Hollywood programming and real-world programming.

Saturday, June 30, 2018

There was a time when search engines were a thing. And it seems they still are

I was poking around in the deeper parts of my harddrive when I came across the source code for Geofind, a metasearch engine I wrote back in the late 90s. A “metasearch engine” is a website that searches not the Internet, but instead passes the search query to other search engines. Back in the 90s, search engines weren't quite as good as they are now (although some might contend that they aren't as good as they were a decade ago), but there were a fair number of them, and the thought at the time was, “hey, if we query a bunch of search engines at the same time, maybe one of them will have useful results.”

In fact, quite a number of them. Unlike the … um … two? (Google and Bing). maybe, three? (if you count DuckDuckGo, which I only know about because of the circles I travel in on the Intarwebs) which exist today.

The last version of the code I have lists 10 engines, although I seem to recall we had as many as 15 at one time. But here's the 10 engines we were querying as of April 1999:

  1. Magellan—once a search engine, now an apartment finder. It's probably not the same company, but I don't know for sure.
  2. Infoseek—the domain is now owned by Disney, which, I think, now owns close to 50% of movies and television.
  3. Lycosis still around! It's still a search engine! As stated on their About page: “Lycos, Inc. is a survivor. Established in 1995, we were originally a search engine ? before most people even knew what a ‘search engine’ was. Times change, and Lycos, Inc. has changed with them, evolving from a single search engine into a focused network of community and social sites that include Gamesville.com, Tripod.com, Angelfire.com, and of course, Lycos.com.” Incredible.
  4. FreeYellow.Com—I think this was a site much like GeoCities, and now, it still exists! Although I don't see a search function, and it's no longer free. Go figure.
  5. Webcrawler—good Lord, it's still around! And apparently, the parent company runs its own metasearch engine.
  6. Yahoostill around … somehow. And they still offer search … somehow.
  7. Alta Vista—is now Yahoo.
  8. Exciteis also around! It's a cluttered page that makes me think they want to be like Yahoo, but hey, they still offer web search.
  9. HotBotit's still around? Really? I mean, Yahoo, yeah, that's still around. But five? In the era of Google? I'm seriously surprised by this.
  10. Goto.com—no longer exists, and the domain now redirects to GoToMeeting, an Internet based collaboration site.

I also found a section of my bookmarks labeled “GeoFind Search Engines,” which includes a few more that weren't listed above. In this list we have:

  1. Clusty the Clustering Engine—I used to use this one (and even offered a search entry that pointed to it on this very site) until they went all in on the Bible Code stuff. They seem to have distanced themselves from the Bible Code stuff sometime in the past eight years though.
  2. Gigablastis still around. And its advanced query page certainly take me back to 1996.
  3. New Rider—redirects to the global mobile operator at sea. Okay.
  4. PointSearchis still around, in the “hyperlocal search” space.
  5. LinkStar—gone entirely. Not even a domain squatter has the domain, that's how dead this one is.
  6. Galaxyis still around. Wow.
  7. Aliweb—gone. All that's left is an article about the site.
  8. Tribal Voice—gone. But unlike LinkStar, the domain is owned by a domain squatter.

What is it with these nearly twenty year old sites still up? I mean, that's great and all, but given that probably 80% of all sites I've linked to in my blog have disappeared, I find it surprising that nearly 50% of the old search engines are still around.

Sunday, July 01, 2018

Replacing the battery on my iPhone should not require rebooting my Mac

It wasn't as bad as that time 2½ years ago (no, really! you have no idea how bad it was back then) but it still left a bad taste in my mouth. The battery on my iPhone wasn't lasting as long as it used to. I would be lucky get to a day's charge out of it, and I don't really use it all that much (using Shazam was a death sentance for my iPhone—I'd usually get one use out of it before the screen would go dark).

On Thursday, Bunny and I stop by the Apple Store only to find out that a battery replacement would require an appointment, and the first one was for Saturday. Okay, Saturday it is.

At the appointed time on Saturday, we arrive at the store. I will say we didn't have to wait all that long, but on the down side, I would have to leave the phone overnight for the replacement.

Okay, picking it up on Sunday it is.

Today, I got the phone back. It works. I was able to check multiple songs with Shazam with no discernible battery drain, so things are looking up. Until I decide to pull some pictures off the phone.

Usually, I just plug in the phone to the Mac-mini I have, run the Photos app and import them. Only this time I coudn't. What should have been a minute operation turned out to be a grueling half hour torture test trying to find out what happened to the “import function” of Photos. I was able to finally resolve the issue by rebooting the Mac-mini!

Seriously, Apple? You're better than Microsoft! This shouldn't require a reboot! Come on!

I swear, they really need to bring back Steve Jobs.

Wednesday, July 04, 2018

All's quiet on the holiday front

Right now it's all quiet outside, but I suspect that won't last the day.

So today, after you have read The Constitution, but before you hand over your beer and say, “Watch this!” please remember to be careful. I would hate for this to happen to you:

[Fireworks that exploded at ground level, with a capture that says, “Amateurs: There's a Reason Professionals Exist.”]

Notes on an overheard conversation

“So the weather report states thunderstorms for the Fourth.”

“Oh! At night?”

“Mostly the afternoon and ending around 8:00 pm.”

“Darn!”

“Oh, expecting to get out of walking to the Boca Raton fireworks show?”

“No.”

“No?”

“No. I was hoping our neighbor wouldn't blow us all up!”


Neither heat nor rain nor threat of thunderstorms stays the neighbor from the swift lighting of firework rounds

It sounds like Desert Storm outside.

[I guess it beats walking down to DeHoernle Park in a potential thunderstorm to watch fireworks.]

I guess the threat of thunderstorms wasn't enough to deter the neighbor.

Sigh.

Thursday, July 05, 2018

Abandon all hope ye who enter the sucking vortex of ill-marked, multply-named, non-Euclidean roadways known as Orlando

Bunny and I are on the road for a weekend getaway (more on that later). We are headed back into that maelstrom of roads known as Orlando. On the downside, said maelstrom has extended itself a significant distance outside of Orlando and for the first time ever, we missed the turn at Ft. Pierce and ended up on a nearly 20 mile detour.

Then, we nearly ended up missing a service station on the Turnpike—don't ask how that happened. It did. And the maelstrom wrought it's malevolent influence over us to the point where we nearly called the whole weekend off.

And finally, Google Maps directed to the rear of the hotel.

I swear, Orlando is actively trying to kill us.


Singing with scissors

Bunny first proposed this trip several months ago and I was initiallty dubious. I mean, a trip to view barbershop quartets! I was reluctant to go, but Bunny assured me that I was under no threat of losing hair or limbs. No, the only thing under threat was the ears.

We finally arrived at the hotel. As we were walking to our room, it seemed to me that barbershop quartets have shrunk over the years, but the lack of matching outfits, no singing and a definite lack of scissors meant that no, the people I was seeing were in fact Little People milling about. Too many to be conincidental and indeed, there really is a conference of Little People scheduled at the same time and not some Lynchian nightmare.

At least, not yet.


About this hotel

The hotel is quite nice, but it has … a few oddities that I've never seen before. The first, and most innocuous, are all the automatic lights about the place. There's one in the bathroom, one beneath the night stand and the entire garage appears to have motion sensative lights (it certainly got brighter in the garage when I went back this evening to pick up a USB cable I left in the car). It was rather unexpected, but a pleasant unexpectedness.

The next was also unexpected, but to me, not a pleasant unexpectedness. The mirror in the bathroom is nice, large and certainly bright:

[Mirror, mirror, on the wall, who's the geekiest of them all?]

But there's this odd greyed out section near the bottom. Here's the not-so pleasant unexpectedness:

[I am, for I have a built in television set and you are just stuck with a smart phone.]

It's a television screen! (and yes, when I turned it on, it was tuned to Fox News. CNN wouldn't have been any better)

Really?

First off, are people so addicted to television that one is needed in the bathroom? [Yes. —Editor]. And second, you can't even watch it while sitting on the toilet! You can only watch the television while standing in front of the mirror. That's just … just … weirdly random.

And finally there is this:

[You may look. You may even touch. But on penalty of death, not not remove the elevator stick from the elevator.]

A stick. In the elevator. Just hanging there with a sign saying not to remove it. And it's not limited to one elevator. No, each elevator has a stick, hanging on a sign saying not to remove it. They're just there. I don't know.

Groups of people singing four part harmony. Little People milling about. Elevator sticks. Automatic lightbulbs. Television mirrors.

Orlando is weird!

Friday, July 06, 2018

Notes on the epiphany I had on elevator sticks while I slept

It may have been obvious to some, but not to me. It suddenly dawned on me what the elevator sticks were all about. The puzzle pieces were all there, I just hadn't made the connection.

I am not the target audience for using the elevator stick, nor is the staff the target audience. No, the target audience is the Little People, so they can use it to push the elevator button in case they can't reach it.

It's obvious in hindsight.

While I joked about the elevator sticks, it's not something I'm used to seeing. And here they were, just hanging out in elevators with no obvious usage to me, some one who can reach all the buttons. It wasn't until I was sleeping and my subconscience told me an old riddle I heard as a kid: “A man lives in a tall apartment building. On some days, he rides the elevator to his apartment on the 20th floor. On other days, he rides the elevator to the 18th floor and walks up two more flights. Why?”

Oh.


“Yeah. ‘Ooh, ah,’ that's how it always starts. But then later there's running and screaming.”

[The other half is the madness that slowly creeps in as you attempt to make sense of the non-Euclidean nature of space around the Kingdom of the Rat God.]

Don't let the propaganda fool you—Orlando is trying to kill you.

Or at least drive you mad and empty your wallet.


One must always make sure to get the cruelty-free pizza

In the lobby of the hotel is a store by the name of “Market Orlando.” I can only describe it as if hippies-cum-yuppies from Berkeley ran 7-Eleven. Gluten-free, organic, farm-fresh snacks, chips, salads and sandwiches.

Oh, and cruelty-free pizzas. Can't forget those.

It has an extensive wine selection (Napa Valley present!), but the soda selection is pretty much limited to Pepsi and Diet Pepsi (which sucks because I'm a Coca-cola person myself). There's also about a bazillion brands of artisanal water.

Oddly enough, I did not see any granola for sale.

I'm telling you, Orlando is weird! When it's not trying to kill you.

Sunday, July 08, 2018

At the roadways of madness

The sucking vortex of non-Euclidean roadways known as Orlando began it's influence of madness over us hours before we left. We were planning on how best to get back to the Turnpike from the hotel when Bunny and I started arguing yet again. She wanted to follow the torturous path we took to get here, which involved an intricate series of turns and switchbacks while carefully aligning ourselves within certain lanes at certain times. I wanted to follow yet another intricate path of a torturous series of turns and switchbacks while carefully aligning outselves within certain times at certain lanes. Either route lead to madness.

Also at stake was who would be the unfortunate driver to brave the maelstrom of roads until the relative safety of the Turnpike. I don't recall who drove. All I know is we barely made it out alive.

Unrelated, I wish to leave you with a mental image of the most surreal observation I saw on the way out of the hotel: a Little Person and their dog riding a Segway down the hall.

Monday, July 09, 2018

At least now no one has to pay to have their information protected

So I received the following email from my registrar:

From
<XXXXXXXX­XXXXXXXX­XXXXXXX>
To
<sean@conman.org>
Subject
WHOIS Data Confirmation for x-grey.com
Date
Mon, 9 Jul 2018 09:30:23 -0400 (EDT)

Dear Valued Customer,

ICANN, the organization responsible for the stability of the Internet, requires that each domain name registrant be given the opportunity to correct any inaccurate contact data (WHOIS data) associated with a domain name registration. Our records for your domain are as follows:

x-grey.com

Domain Name: X-GREY.COM
Registry Domain ID: 1325416434_DOMAIN_COM-VRSN
Registrar WHOIS Server: whois.domain.com
Registrar URL: www.domain.com
Updated Date: 2017-11-08T05:11:47
Creation Date: 2017-11-07T22:32:17
Registrar Registration Expiration Date: 2018-11-08T01:32:21
Reseller: Dotster.com
Domain Status: clientTransferProhibited https://icann.org/epp#clientTransferProhibited
Domain Status: clientUpdateProhibited https://icann.org/epp#clientUpdateProhibited
Registry Registrant ID:
Registrant Name: Data Protected Data Protected
Registrant Organization: Data Protected
Registrant Street: 123 Data Protected
Registrant City: Toronto
Registrant State/Province: ON
Registrant Postal Code: M6K 3M1
Registrant Country: CA
Registrant Phone: +1.0000000000
Registrant Phone Ext:
Registrant Fax: +1.0000000000
Registrant Fax Ext:
Registrant Email: noreply@data-protected.net
Registry Admin ID:
Admin Name: Data Protected Data Protected
Admin Organization: Data Protected
Admin Street: 123 Data Protected
Admin City: Toronto
Admin State/Province: ON
Admin Postal Code: M6K 3M1
Admin Country: CA
Admin Phone: +1.0000000000
Admin Phone Ext:
Admin Fax: +1.0000000000
Admin Fax Ext:
Admin Email: noreply@data-protected.net
Registry Tech ID:
Tech Name: Data Protected Data Protected
Tech Organization: Data Protected
Tech Street: 123 Data Protected
Tech City: Toronto
Tech State/Province: ON
Tech Postal Code: M6K 3M1
Tech Country: CA
Tech Phone: +1.0000000000
Tech Phone Ext:
Tech Fax: +1.0000000000
Tech Fax Ext:
Tech Email: noreply@data-protected.net
Registry Billing ID:
Billing Name: Data Protected Data Protected
Billing Organization: Data Protected
Billing Street: 123 Data Protected
Billing City: Toronto
Billing State/Province: ON
Billing Postal Code: M6K 3M1
Billing Country: CA
Billing Phone: +1.0000000000
Billing Phone Ext:
Billing Fax: +1.0000000000
Billing Fax Ext:
Billing Email: noreply@data-protected.net
Name Server: ns1.armigeron.com
Name Server: ns2.armigeron.com
URL of the ICANN WHOIS Data Problem Reporting System: http://wdprs.internic.net/
>>> Last update of WHOIS database: 2017-11-08T05:11:47 <<<

“For more information on Whois status codes, please visit https://icann.org/epp”

Registration Service Provider:
    XXXXXXXX­XXXX XXXXXXXX­XXXXXXXX­XXXXXXX
    +1.X­XXXXXXXX­X
    This company may be contacted for domain login/passwords,
    DNS/Nameserver changes, and general domain support questions.

To review and update your WHOIS contact information, please log into our management interface at: XXXXXXXX­XXXXXXXX­XXXXXXXX­XXXXXXXX­XXX

If any of the information above is inaccurate, you should correct it. If all of the information above is accurate, you do not need to take any action.

Please remember that under the terms of your registration agreement, the provision of false WHOIS information can be grounds for cancellation of your domain name registration. If you have any questions or comments regarding ICANN's policy, please visit the following link http://www.icann.org/registrars/wdrp.htm

Thank you for your attention.

Best regards,
XXXXXXX

It's kind of hard to review my information when it's protected from my viewing it for my protection. I think my registrar is going a bit overboard in complying with the GDPR.

Sigh.


Yes. It is music. I identified it. What more do you want?

Bunny and I had dinner at a nearby Chinese restaurant. As we ate, Bunny mentioned that the music we were listening to must be the Chinese equivalent to elevator music. I concurred, and because I was curious to know what it was, I thought I might try to use Shazam to identify it.

It did.

[Of course!  It was obvious!]

And now I know.

Monday, July 16, 2018

I don't think this is what McDonald's had in mind when they said “you deserve a break today”

I was at The Scottish Place to pick up some lunch. I placed my order, and while waiting in line, I noticed the telltale signs of Microsoft Windows:

[Image of a crashed Windows box: A stopped clock is right twice a day, unless it's one of those 24-hour clocks which makes it right only once a day, but a crashed Windows box isn't right at any time of day (and some would say that even a functioning Windows box isn't right at any time of the day, but I digress ...)]

Ah, Windows, keep on being your special snowflake self.

But in all seriousness, who set this up? If you are going to run any computer in a public space, I would hope those setting it up would run the bare minimum for the service required (and in this case, just the operating system and whatever program it is that runs the display) and remove everything else. Then, for whatever left is running, is there not some Windows setting to just have it automatically reboot upon an error? Or simply not display warning messages like this on the display meant for public viewing?

I have to wonder how long this message has been here, waiting for someone, anyone, to select an option (or to restart, reboot or reinstall). I wonder if management even cares?

Thursday, July 19, 2018

A sane and easy to use TLS library! Will wonders never cease!

I'm still fighting the stupidity at work, but it's becoming aparent that it's a fait accompli and we're looking at a bunch of REST/HTTPS über alles Kool-Aid™ in an area where time is critical.

Sigh.

So I'm looking around at what I can use to support the “S” in HTTPS that doesn't involve diving into the horror show that is OpenSSL. A library that can still encrypt and decrypt data when it isn't managing the network connections on the program's behalf (because the program is already managing the network connections). It can be complicated, but it must be sane to use.

I was pointed to libtls, which comes with LibreSSL. Not only is this sane, but it's easy to use. I'm simply amazed at how easy.

In just an hour, and only reading the man pages, I was able to write a simple program that fetches a page from a secure website. And most of the code is just there to report any errors that happen. It's a very straight forward program.

Another hour or two, and I had a program where the library does not control the network connection. Which means we can (probably) use this in our existing architecture.

A few more hours, and I was able to replicate the initial C program in Lua:

local tls = require "org.flummux.tls"

-- *****************************************************************

local function okay(v,err)
  if not v then
    print(">>>",err)
    os.exit(1)
  end
  return v
end

-- *****************************************************************

if #arg == 0 then
  io.stderr:write(string.format("usage: %s host resource\n",arg[0]))
  os.exit(1)
end

local config = tls.config()
local ctx    = tls.client()

okay(config:set_protocols "all")
okay(ctx:configure(config))
okay(ctx:connect(arg[1],"https"))
okay(ctx:write(string.format(
     "GET %s HTTP/1.1\r\n"
  .. "Host: %s\r\n"
  .. "User-Agent: TLSTester/1.0 (TLS Testing Program Lua)\r\n"
  .. "Connection: close\r\n"
  .. "Accept: */*\r\n"
  .. "\r\n",
     arg[2],
     arg[1]
)))

while true do
  local bytes = okay(ctx:read(1024))
  if bytes == "" then break end
  io.stdout:write(bytes)
end

I had to write my own Lua wrapper for LibreSSL. The existing ones (and I found only two) weren't up to my standards for use, but it wasn't terribly hard to get the above working.

The next step is expanding the Lua module to see if I can get it working with our networking code we use. I am optimistic about this.

But I am not optimistic about having to use this at work.

Monday, July 23, 2018

Managing TLS connections using Lua and Lua coroutines

Getting libtls working with Lua wasn't as straightforward and I thought it would be. It works (for the most part) but I had to change my entire approach. The code is an ugly mess and there's quite a bit of duplication in several spots.

But! I can request web pages, in Lua, via HTTPS in an event loop based around select() (or poll() or epoll() or whatever is the low level event notification scheme used). Woot! And I'm going into excruciating detail on this.

Back on Friday, when I wrote some “proof-of-concept” code, I had thought I could switch coroutines in the user-supplied I/O callback routines (and if coroutines existed in C, that is where you would yield to another coroutine). It was easy enough to extend the callback to a Lua routine— in the routine that wraps the libtls function tls_connect_cbs():

static int Ltls_connect_cbs(lua_State *L)
{
  struct tls **tls = lua_touserdata(L,1);
  int rc           = tls_connect_cbs(
			*tls,
			Xtls_read,
			Xtls_write,
			L,
			luaL_checkstring(L,2)
		     );
  
  if (rc != 0)
  {
    lua_pushboolean(L,false);
    return 1;
  }
  
  lua_settop(L,5);
  lua_pushlightuserdata(L,*tls);
  lua_getuservalue(L,1);
  lua_pushvalue(L,1);
  lua_setfield(L,-2,"_ctx");
  lua_pushvalue(L,2);
  lua_setfield(L,-2,"_servername");
  lua_pushvalue(L,3);
  lua_setfield(L,-2,"_userdata");
  lua_pushvalue(L,4);
  lua_setfield(L,-2,"_readf");
  lua_pushvalue(L,5);
  lua_setfield(L,-2,"_writef");
  
  lua_settable(L,LUA_REGISTRYINDEX);
  lua_pushboolean(L,true);
  return 1;
}

I pass in the two callback functions, and I'm using the Lua state context as the userdata in the callbacks. I then create a Lua table, populate it with some useful information, such as the Lua functions to call, and associate it in the Lua registry with the value of the libtls context. Then, when libtls calls one of the callbacks:

static ssize_t Xtls_write(struct tls *tls,void const *buf,size_t buflen,void *cb_arg)
{
  lua_State *L = cb_arg;
  ssize_t    len;
  
  lua_pushlightuserdata(L,tls);
  lua_gettable(L,LUA_REGISTRYINDEX);
  lua_getfield(L,-1,"_writef");
  lua_getfield(L,-2,"_ctx");
  lua_pushlstring(L,buf,buflen);
  lua_getfield(L,-4,"_userdata");
  lua_call(L,3,1);
  
  len = lua_tonumber(L,-1);
  lua_pop(L,2);
  return len;
}

I get the Lua state via the user argument. From that, and the libtls context, I obtain the data I cached into the Lua table, which give me the Lua function to call. Said function can then call coroutine.yield().

Straightforward, easy, and wrong! I got the dreaded “attempt to yield across metamethod/C-call boundary” error. Darn.

The attempted flow looks like (yellow boxes are Lua functions; green boxes are C functions):

{data=tls.read()} → [Ltls_read(lua)] → [tls_read(ctx)] → [Xtls_read(ctx,lua)] → [lua_call(lua)] → {my_callback()} → {coroutine.yield()} {}=Lua function []=C function

There are four layers of C functions that can't be yielded through. Lua does have a way of dealing with intervening C functions, but it's somewhat clunky.

{luaf_a()} → [cf_orig(lua)] → [lua_callk(lua,cf_c)] → {luaf_b()} → {coroutine.yield} / {coroutine.resume} → {luaf_b()*} → [cf_c(lua)*] → {luaf_a()}

In this case, the Lua function lua_callk() is handled specially so it doesn't cause an error. The function cf() needs to be split in half—the portion prior to calling into Lua, and the second half to handle things after a potential call to coroutine.yield(). That's represented above by the functions cf_orig() and cf_c(). The “*” represent the functions returning, not calling. coroutine.resume() will restart luaf_b() right after it's call to coroutine.yield(). And when luaf_b() returns, it “returns” to cf_c(), which does whatever and finally returns, which “returns” to luaf_a().

But in the case I'm dealing with just doesn't work with that model. The code calling into Lua doesn't have the signature:

int function(lua_State *lua_State);

but the signature:

ssize_t function(struct tls *ctx,void *buf,size_t buflen,void *cb_arg);

Not only are the return types different, but they have completely different semantics—for libtls, it's the number of bytes transferred, whereas for Lua, it's the number of items being returned to Lua.

No, I had to rethink the entire approach, and do the call to coroutine.yield() a bit higher in the call stack. Which also meant I had to push dealing with TLS_WANT_POLLIN and TLS_WANT_POLLOUT back to the caller. The documentation states:

In the case of blocking file descriptors, the same function call should be repeated immediately. In the case of non-blocking file descriptors, the same function call should be repeated when the required condition has been met.

And here I was, trying to hide such concerns from the user. Ah well.

I eventually got it working, but man, is it ugly. The Lua code wants to read data, so I have to call into libtls. That in turn, calls back into my code, and if I don't have any, I need to return TLS_WANT_POLLIN, which bubbles up through libtls back to my code, which can then yield.

Meanwhile, from the other end, I get data from the network. I can't just feed it into libtls, I have to feed it when libtls calls the callback for the data. But when I get the data, I may need to resume the coroutine, so I have to track that information as well.

I can almost understand the code (and yes, I wrote it; did I mention it's ugly?)

But I'm happy. The following code works in my existing network framework (boy does that sound wierd):

local function request(item)
  syslog('debug',"requesting %s",item.url)
  local u = url:match(item.url)

  -- -------------------------------------------------------
  -- asynchronous DNS lookup---blocks the current coroutine
  -- until a result is returned via the network.
  -- -------------------------------------------------------

  local addr = dns.address(u.host,'ip','tcp',u.port)
  
  if not addr then
    syslog('error',"finished %s---could not look up address",u.host)
    return
  end

  -- ---------------------------------------------------------
  -- This has nothing to do with the iPhone operating system,
  -- but everything to do with "Input/Output Stream"
  -- ---------------------------------------------------------

  local ios
  
  if u.scheme == 'http' then
    ios = tcp.connecta(addr[1]) -- connect via TCP
  else
    ios = tls.connecta(addr[1],u.host) -- connect via TLS
  end
  
  if not ios then
    syslog('error',"could not connect to %s",u.host)
    return
  end
  
  local path    = table.concat(u.path,'/')
  local fhname  = "header/" .. item.hdr
  local fbname  = "body/"   .. item.body
  local fh      = io.open(fhname,"w")
  local fb      = io.open(fbname,"w")
  
  local command = string.format([[
GET /%s HTTP/1.0
Host: %s
Connection: close
User-Agent: TLSTest/2.0 (Lua TLS Testing Program)
Accept: */*

]],path,u.host)

  ios:write(command)
  
  fh:write(ios:read("*h"))
  
  repeat
    local data = ios:read("*a")
    fb:write(data)
  until data == ""
  
  fb:close()
  fh:close()
  ios:close()

  syslog('debug',"finished %s %s",item.url,tostring(addr[1]))
end

Any number of requests can be started and they all run concurrently, which is just what I wanted.

Now, the code I have for the Lua wrapper for libtls covers just what I need to do this. More work is required to finish covering the rest of the API. I also have to clean up the Lua code that backs the above sample code so that I might have a chance of understanding it at some point in the future.

And until I get the working code published, you can look at the “proof-of-concept” Lua coroutine code I worked from (and no, the above code sample will not work as is with this “proof-of-concept” code).

Monday, August 06, 2018

I guess we'll see how well CBOR works

The Corporate Overlords of The Corporation have spoken, and lo, they said “Worry not, for you do not have to deal with the stupidity—we shall deal.” So great, we don't have to drink the REST/HTTPS über alles Kool-Aid™, but instead query our Corporate Overlords for the data, who have drunk the REST/HTTPS über alles Kool-Aid™ (or were forced to by the company we query for the data—the end effect is the same though).

Sigh.

So for now, we still make our queries via UDP, only now in CBOR—the legacy format of DNS is apparently too arcane to support any more.

I have a Lua module but we also need one in C. There are some existing ones, but they have their issues (either an alien build system or missing some critical CBOR feature) so I've been working on a C library I started a few years ago and never finished.

It's working now, and to test it, I've been using valgrind to ensure memory safety, in addition to using /dev/urandom to generate random garbage:

GenericUnixPrompt% dd if=/dev/urandom count=2 | tee bad-data | valgrind ./testdecoder

dd is one of those relatively arcane Unix programs that I find useful on occasion (like here to generate some random data). tee I use to record the data so I can play it back when valgrind finds an issue. This is a reasonable way to fuzz a program. It did find several issues that could have lead to a crash, and I don't leak any memory so the code should be good to go.


It seems that checking the TLS API version number is useless

I've pretty much finished the Lua TLS module and before releasing it, I thought it might be nice to ensure it compiles with previous versions of libtls. The main header file contains the defined value TLS_API, which I assume is updated whenever the API is updated. So I began the arduous procedure of downloading previous versions of libtls to ensure I can compile against any version.

I started with LibreSSL version 2.7.4 (current when I started—they are now up to 2.8.0 as I write this). The defined value TLS_API had a value of “20180210”. I checked version 2.7.0 and no change in libtls. It wasn't until I got into the pre-2.7 versions that things started going south.

The previous version of TLS_API, “20170126”, was first defined in 2.5.1, and last used in 2.6.5. But the API changed quite a bit between versions 2.5.1 and 2.6.5. Five functions were added:

  1. tls_config_set_crl_file()
  2. tls_config_set_crl_mem()
  3. tls_config_set_ecdhecurves()
  4. tls_peer_cert_chain_pem()
  5. tls_unload_file()

What's the point of having a defined value like TLS_API if it doesn't change when you add new functions?

Fortunately, the defined value LIBRESSL_VERSION_NUMBER is updated per version, so at least I can use that.

Sigh.

Tuesday, August 07, 2018

All I'm asking for is some consistency between APIs and version numbers

When I first started working with libtls, I thought that TLS_API designated a change in API so that one could work with different versions of the library without breaking the compilation process. Sadly, that wasn't the case, so I switched to using LIBRESSL_VERSION_NUMBER, as that seemed to regularly change with each version.

I was doing this so that my Lua wrapper could be compiled with any version of libtls. Why break things unnecessarily? And things were going fine until I hit version 2.2.1, and well …

Mismatches in libtls between functions added, LIBRESSL_VERSION_NUMBER and TLS_API
Version Functions LIBRESSL_VERSION_NUMBER TLS_API
Version Functions LIBRESSL_VERSION_NUMBER TLS_API
2.1.2
  • tls_accept_socket()
  • tls_client()
  • tls_close()
  • tls_config_clear_keys()
  • tls_config_insecure_noverifycert()
  • tls_config_insecure_noverifyhost()
  • tls_config_set_ca_file()
  • tls_config_set_ca_path()
  • tls_config_set_cert_file()
  • tls_config_set_cert_mem()
  • tls_config_set_ciphers()
  • tls_config_set_ecdhcurve()
  • tls_config_set_key_file()
  • tls_config_set_key_mem()
  • tls_config_set_protocols()
  • tls_config_set_verify_depth()
  • tls_config_verify()
  • tls_configure()
  • tls_connect()
  • tls_connect_fds()
  • tls_connect_socket()
  • tls_error()
  • tls_free()
  • tls_init()
  • tls_read()
  • tls_reset()
  • tls_server()
  • tls_write()
0x20000000 20141031
2.1.4
  • tls_load_file()
0x20000000 20141031
2.2.0
  • tls_accept_fds()
0x20000000 20141031
2.3.0
  • tls_config_insecure_noverifytime()
  • tls_config_prefer_ciphers_client()
  • tls_config_prefer_ciphers_server()
  • tls_config_verify_client()
  • tls_config_verify_client_optional()
  • tls_conn_cipher()
  • tls_conn_version()
  • tls_handshake()
  • tls_peer_cert_contains_name()
  • tls_peer_cert_hash()
  • tls_peer_cert_issuer()
  • tls_peer_cert_provided()
  • tls_peer_cert_subject()
  • tls_read() (paramter change)
  • tls_write() (parameter change)
0x20030000 20141031
2.3.1
  • tls_peer_cert_notafter()
  • tls_peer_cert_notbefore()
0x20030001 20141031
2.4.0
  • tls_config_keypair_file()
  • tls_config_keypair_mem()
0x2040000f 20141031
2.5.0
  • tls_accept_cbs()
  • tls_config_add_keypair_file()
  • tls_config_add_keypair_mem()
  • tls_config_alpn()
  • tls_conn_alpn_selected()
  • tls_conn_servername()
  • tls_connect_cbs()
0x2050000f 20160904
2.5.1
  • tls_ocsp_process_response()
  • tls_peer_ocsp_cert_status()
  • tls_peer_ocsp_this_update()
  • tls_peer_ocsp_url()
  • tls_config_add_keypair_ocsp_file()
  • tls_config_add_keypair_ocsp_mem()
  • tls_config_add_ticket_key()
  • tls_config_keypair_ocsp_file()
  • tls_config_keypair_ocsp_mem()
  • tls_config_ocsp_require_stapling()
  • tls_config_ocsp_staple_file()
  • tls_config_ocsp_staple_mem()
  • tls_config_session_id()
  • tls_config_session_lifetime()
  • tls_peer_ocsp_crl_reason()
  • tls_peer_ocsp_next_udpate()
  • tls_peer_ocsp_response_status()
  • tls_peer_ocsp_revocation_time()
0x2050100f 20170126
2.6.0
  • tls_config_crl_file()
  • tls_config_crl_mem()
  • tls_peer_cert_chain_pem()
  • tls_unload_file()
0x2060000f 20170126
2.6.1
  • tls_config_echdecurves()
0x2060100f 20170126
2.7.0
  • tls_config_session_fd()
  • tls_conn_session_resumed()
0x2070000f 20180210

I'm not asking for much. I'm not asking for slavish adherance to semantic versioning. I'm just asking for a consistent way to check an API to I can support earlier versions of a library.

Don't get me wrong, I'm glad that libtls exists, and as an API, it's much nicer than the eldritch horror of OpenSSL.

I just wish they had updated TLS_API (or LIBRESSL_VERSION_NUMBER) consistently. Otherwise, why have them in the first place?


Oh wait … I see now … send a completely crazy email so I'll post it

I get quite a bit of spam asking to add links to old entries. It's clear that they do a search for something like “Lost Wages” and spam the XXXX out of people who link to any page dealing with their search term. But the one I received yesterday …

From
Adam Conrad <adam@shihtzuexpert.com>
To
sean@conman.org
Subject
Article Contribution on Boston.Conman.Org
Date
Mon, 6 Aug 2018 23:38:14 -0700

Sean,

I really like the post on your site at http://boston.conman.org/2007/12/27.1

I’ve also, been writing about Shih Tzu and other small, toy or medium breed dogs and related issues like health, food etc at

The Shih Tzu Expert

http://shihtzuexpert.com/canine-distemper/

I would love the chance to write a unique and an interesting guest post for your blog.

I can write about any topic related to pets.

Our articles are 700+ words, written by native English speakers/writers.

Our content is unique, fresh, detailed, and thoroughly researched.

If it covers medical issues or advice, we always require our in house veterinarian to check accuracy of facts before publication.

A selection of titles we are proposing

If there is any topic you want us to cover, please feel free to let us know.

Please feel free to contact me if you have any questions.

Best regards,

Adam Conrad

ShihTzuExpert.com

Seriously … WTF?

The page Adam linked to?

Nothing to do with dogs!

I have entries where I talk about dogs. And cats. And dogs and cats. It's not like Adam lacked entries to choose from.

But nooo! Adam choose one sans dogs.

What?


Notes on an overheard conversation in a typical company lunch room

“Nice music.”

“It's classical.”

“Classical? That's modern jazz.”

“It's Gershwin. He's white, and he's dead. Therefore, it's classical.”

“So is Kurt Cobain, but I don't consider his music classical.”

Friday, August 10, 2018

Just a small observation about an email I received at work

I'm checking the work email and lo, there's email from our Vice President of Product Management requesting us, unironically, to wear our Corporate flair.

Tuesday, August 21, 2018

Not anyone should be allowed to run a debugger

I'm working on “Project: America-­On-­Line-­Instant-­Messenger” (hey, don't judge me—it has nothing to to with AOL, it's more a pun on the project name than anything else). I've got a major portion of it running, but it's exhibiting some odd behavior—it runs fine on Linux, but fails rather quickly on Mac OS-X with “not enough memory.”

Problem one—I'm used to using gdb, but Mac OS-X uses lldb. Sigh. I did find a type of Rosetta Stone that shows similar commands in both gdb and lldb, so that issue is solved.

I was then able to track down the message to a source file in LPeg, but when I set a breakpoint on the line in question, it never got triggered. Puzzling, but I was not able to solve the issue by the time I had to leave work.

So now I'm home and I have an idea to scan more than just the .c files. It's a simple matter to log into my Mac workstation at work to see if that's the issue. I start looking, and lo, I find the message in two more locations, hidden behind a #define in a header file. I narrow it down to just one location (the other location pre-loading the string into the Lua VM).

First, the lldb commands are bit more verbose than those of gdb. Second, no matter what I do, all I get is:

[spc]XXXXXXXX­XXXXXXXX­XXXXXXXX­X>lldb XXXXXXX­XX
(lldb) target create "XXXXXX­XXX"
Current executable set to 'XXXXX­XXXX' (x86_64).
(lldb) process launch -- config.lua
error: process exited with status -1 (lost connection)
(lldb) 

Nothing I do works.

Then I remember—when I first ran lldb at the office, this modal dialog box popped up asking for my password in order to debug a program I wrote, running under my account. My initial reaction is, Smooth going, Apple! Way to protect me from myself! But then I realize this is probably to prevent rogue programs trying to attach to running programs to do nefarious things without my knowledge.

It's bad enough I have to jump through hoops to get the computer to run my own written programs. Now this?

XXXX!

It really does seem at times as if the general purpose computer is a dinosaur looking up at the sky, wondering, “What is that?”

Wednesday, August 22, 2018

I don't need no steeeenking debugger

I was still having troubles with lldb accepting breakpoints; the breakpoints were just not being hit. Thinking about the issue, it seemed to me that the code might be requesting a too large amount of memory and an easy eay to do that is to track all allocations made by Lua. It was easy enough to test:

static void *l_alloc(void *ud,void *ptr,size_t osize,size_t nsize)
{
  (void)ud;

  fprintf(stderr,"osize=%zu nsize=%zu\n",osize,nsize);

  if (nsize == 0)
  {
    free(ptr);
    return NULL;
  }
  else
    return realloc(ptr,nsize);
}

int main(int argc,char *argv[])
{
  /* ... */

  L = lua_newstate(l_alloc,NULL);

  /* ... */
  return 0;
}

Then it was a simple matter of running the program and check each allocation:

 ...
osize=0 nsize=64
osize=0 nsize=40
osize=0 nsize=64
osize=0 nsize=0
osize=0 nsize=64
osize=0 nsize=16
osize=0 nsize=64
osize=0 nsize=0
osize=0 nsize=160
osize=0 nsize=148
osize=0 nsize=64
osize=0 nsize=16
osize=16 nsize=32
osize=0 nsize=16
osize=0 nsize=64
osize=0 nsize=18446744073709551600
 ...

Hmmmmm

Okay, force a core dump we can examine:

static void *l_alloc(void *ud,void *ptr,size_t osize,size_t nsize)
{
  (void)ud;
  (void)osize;

  if (nsize > 10uL * 1024uL * 1024uL)
    abort(); /* dump core! */

  if (nsize == 0)
  {
    free(ptr);
    return NULL;
  }
  else
    return realloc(ptr,nsize);
}

And the problem is immedately resolved.

The Linux version used epoll() for events, while for whatever reason I don't remember, the Mac OS-X version used select() [Yes, I know that's a Linux reference and not a Mac OS-X reference, but the call is the same between the two systems, and I couldn't find a version of the Mac OS-X page online. —Sean], and that code path was … a bit problematic.

The fix was easy—use poll() for events. With that change, the code worked fine on Mac OS-X (not that we use Mac OS-X in production, but it makes it easy to test in development if it works on the Mac).

Thursday, August 23, 2018

The sad thing is, it's not so bad it's amusingly bad, it's just bad

JC, a fellow cow-orker, casually said he was going to throw out an Android tablet as it was garbage. It worked, but apparently was so bad that it wasn't worth keeping. I was curious. So I asked him if I could have it instead.

Wow.

I think I should ask for my money back.

How much of the badness is due to Android and how much of it is due to this being the Mi Traveler10Q8B I don't know. I think I'm willing to give Android the benefit of a doubt, seeing how it can be modified by the OEM to fit their needs, so I'm attributing all the badness to the Mi Traveler10Q8B.

And it's baaaaaaaaaaad!

Weight-wise, it's about the same as my iPad, but boy does it feel cheap. The screen is cheap plastic. The case is cheap plastic. It feels like I can pry it apart, although it's a sealed case and extensive probing doesn't reveal any obvious seams. It just feels … cheap!

It took me a bit to figure out how to turn the unit on. There are two switches on one edge (top? Bottom? Hard to say), both identical. One turns the unit on and off. the other one is the “Home” button.

Using it, It seems slugish as I'm using it. I've never been fond of Android (having been spoiled by the iPhone) but this thing is just painful to use. The interface is confusing (and again, I'm not sure how much of this is Android and how much of this is the Mi Traveler changing things up to “add value”) and the tentacles of Google are very much evident here—no I do not want to use the Google Butt Cloud thank you very much. Then there's the YouTube app. Why does it need my contacts, location, use of the camera and microphone and the ability to send an SMS? Bad Google! No cookie for you!

And now we get to the camera.

It's bad. It's really bad.

My iPhone takes better pictures. So does the iPad.

In fact, to get a picture as bad as the Mi Traveler, I had to crank the quality of the image down to 10%, and even then, I still think the picture is better than the one from the Mi Traveler.

It might be fun to hack on though.

Now … where did I put my pick-axe?

Friday, August 24, 2018

Musings on the intersectionality of trigger warnings and spoiler warnings

I was reading XXX XXXXXXXX­X XXXXX XXXX XX XXXXXXX [Hold it right there! You need a trigger warning for that link! –Editor] [Sigh. Fine. –Sean]

(TRIGGER WARNING: X­XXXXXXXX­X XXXXXXX XXXXXXX) [STOP! SPOILER! Where's the spoiler warning? –Editor] {Seriously? I was trying to give a trigger warning, and now you want a spoiler warning as well? –Sean] [Yes. We can't just go X­XXXXXXX X XXXXX XXXXXX! –Editor] [Isn't that a spoiler as well? You can't say that if I can't say XX­XXXXXXXX­ XXXXXXX XXXXXXX –Sean] [… –Editor] [Well? –Sean] [Deep subject. But yes, you are correct. Carry on. –Editor]

SPOILER WARNING: The following trigger warning contains a spoiler for …

[Okay, so how I am supposed to do this? I need to both give a spoiler warning and a trigger warning for the page, but the trigger warning contains a spoiler. If you don't want to get spoiled, you could potentially get triggered. But if I give the trigger warning, those who hate spoilers will have the story ruined! What now, high and mighty editor? –Sean]

[Well, you are well and truly X­XXXXX! –Editor]

[Trigger warning for the foul language, you XXX­XXXX! –Sean]


Some musings on a fable of software engineers

[You might want to read this first. –Editor] [Really? –Sean] [Really. Or don't. But don't say I didn't warn you. –Editor] [Sigh. –Sean]

I was reading The Codeless Code: Case 41 Garbage (link via Lobsters) and my initial thought was that the head monk might not have much experience with source control. I know I only first started using source control back in 2000 (CVS) and not to control multiple versions but to allow an easy method to update the code from a remote location. Before the use of source control, I found myself commenting out code to keep it “just in case.”

These days, I no longer keep commented out code (erm … um … okay, I should probably just remove the code and convert the information into a real comment) but the thought did strike me that, okay, I remove the code but I have to remember the code existed at one point. Or a maintainer will have to be cognizant enough to search the history looking for deleted code that could be useful. There's very little indication of code that's been removed.

Just a thought.

Tuesday, September 11, 2018

A view from the Ft. Lauderdale Office of the Corporation

The building was trembling. This isn't unusual as there's a railroad running along side the building. But what was unusual was the lack of a train. Then a loud thud and finally silence. A few of us looked out the window.

[We might want to get Reba McEntire and Michael Gross on the phone in case this happens again.]

There, in a freshly dug trench that didn't exist moments earlier, was a dead graboid. It must have slammed into the foundation of I-95, which runs along the other side of the building.


Some notes on project names at The Ft. Lauderdale Office Of The Corporation

I was asked about the projects I've mentioned on the blog by a fellow cow-orker, D, and I thought I should summarize them.

First is “Project: Wolowizard.” This used to refer to the entire suite of programs my team (that is, the team I work on, not the team I manage—I'm not a mangager) is responsible for.

Then I wrote “Project: Sippy-Cup to interface with the new hipster hotness. This ended up calling into the same backend as “Project: Wolowizard.” So now it seems silly to consider the backend as part of “Project: Wolowizard” when it's used by two different front ends (the other frontend interfaces with The Protocol Stack From Hell). I'm now going to refer to the common backend as “Project: Lumbergh” (it makes sense if you know the actual name of the program).

And that leaves “Project: America-­On-­Line-­Instant-­Messenger,” the latest program to be written. My fellow cow-orker T gave it its initial name, but no one, not even he, really liked the name. After some discussion it was renamed, and thus I'm giving it a new name here in the blog—“Project: Cleese” (which again, makes total sense if you know the new name and the context in which it was named).

There are some other programs we're responsible for, but as they are rarely touched I'm not going to bother mentioning them. It's mostly legacy stuff anyway and they will most likely go away when The Protocol Stack From Hell is sent back from whence it came (and believe me, it can't happen soon enough).

Sunday, September 16, 2018

Before the Pink Panther there was Peter Gunn

Bunny has been binge watching “Peter Gunn” and I have to say, the music is fantastic! The only other TV shows that had as jazzy a score were “Twin Peaks” and “Cowboy Bebop.” I wish more shows used a jazz sound track, it's fun just to listen to the music.

Tuesday, September 18, 2018

This is why I tend towards writing my own code libraries

Six years ago I had the need to fetch an image via HTTP as part of testing “Project: Lumbergh.” At the time, I thought You know what? Why don't I use libcurl? It's installed. It's supposedly easy to use. It'll save me the hour or so it'll take me to write the code to connect to the server, send the request and read the reply.

It still took about an hour, mainly to figure out how to use the darned library. But it worked.

And then I went to test on Solaris (which is what production runs on) and well …

r2839 | spc | 2012-07-11 14:22:27 -0400 (Wed, 11 Jul 2012) | 8 lines

[Testing]

It's amazing what isn't installed on Solaris.

And yes, I do use curl for testing. Easy (if insanely large) library to use to snarf down web requests.

I had to download libcurl and check it into the repository because it's not on Solaris.

And then I had to figure out the special ./configure options to get it compiled under Solaris.

And then I had to wait for ./configure and make to run (and on Solaris, this is a S—L——O———W————P—————P——————R———————O————————C—————————E——————————S—————————————S).

And then I had to figure out how to integrate this into the build system for Solaris.

And for something that was supposed to be “easy to use” turned out to be not so easy. Nor quick. And has been a thorn in my side these past six years.

Seven years ago I wrote a Lua module to generate hashes. Instead of pulling the code from various RFCs, I thought I would link to OpenSSL, since it already included the code for the various hashes, and who knows—it might even be optimized.

This only took a few moments to implement and was rather easy.

Until Apple decided to deprecate the use of OpenSSL on Mac OS-X and later remove OpenSSL in their latest offerings.

I use said Lua module at work.

We mostly develop under Mac OS-X.

Sigh.

This has become a thorn in my side over the past few years. The issue came up two weeks ago when my fellow cow-orker TS, decided to update his Mac OS-X laptop and the build broke. And it came up today because my other fellow cow-orker TS-II (same initials—go figure) did some update or other on his Mac OS-X laptop and the build broke, but in a different way (wow—to think that each version of Mac OS-X is a special snowflake).

Two libraries, used to avoid the whole “Not Invented Here Syndrome” and to speed up development.

In both cases, it has not speed up development. It has slowed down development as I've had to find more and more ways to keep using these infernal libraries.

I guess I'll spend a few hours ripping out libcurl and OpenSSL and replacing it with code I've written to speed things up around here.

Thursday, September 27, 2018

Brevard or Bust

Bunny and I left at O'dark 30 for our yearly trip to Brevard and we made excellent time. The plan, as was usual, was I drive until the sun comes up, letting Bunny get a bit more sleep, then we switch places where she drives and I sleep.

[I wear ear protectors so that Bunny can listen to whatever radio station she wants while driving.  I also have ear buds in, listening to “A Huge Ever Growing Pulsating Brain That Rules From The Centre Of The Ultraworld” as I sleep.  All hail our new Ultraworld overlords!]

11½ hours later we arrived at The Red House Inn, our favorite place to stay. We were fortunate in there being a break in the rain to let us unload the car, and it was then when I had the horrible realization that my iPad (which I use as a laptop while on vacations) was 750 miles away, sitting were I left it at Chez Boca.

Sigh.

Obviously I have work arounds, but it's still annoying.

Anyway, we're just relaxing after a long drive and will shortly have dinner at The Square Root.

Friday, September 28, 2018

An inadvertent lock-out, Brevard edition

Bunny and I are taking it easy on the first day of vaction. The weather is nice—sun is out, temperature is mid-70s, and there's the sound of the neighbor mowing his rather sizable lawn.

[Nothing like a private porch to spend a late summer afternoon (yes, I know it's technically autumn right now). You wish you were here.]

So I'm sitting on the private porch at The Red House Inn when I attempt to check my email. I can't.

You see, I use mutt to read my email. It runs directly on my email server, but to log into my email server, I have to first log into my home system due to filtering of ssh attempts by the hosting company (which doesn't really bother me all that much). But I too, have some filtering going on at home. I programmed my own syslog daemon to block ssh attempts after five times, regardless of time between attempts, or, as it turns out, regardless of sucessful attempts!

Because I left my iPad at home, I'm having to type my password. And due to the keyboard I'm using (it's not a Model M keyboard and therefore by default, this keyboard sucks) I incurred a few failed log in attempts.

Oops.

Well, that sucks! I thought. Wait! I know! I can log into work over The Corporation's VPN to my workstation there, and from there I can log into home and fix the situation. The problem became logging into the VPN.

And now I have two problems.

I called a fellow cow-orker, D, but he did not have the information I needed to configure the VPN, but as I was working on it, the idea came that all I really needed was a different Wi-Fi network to log in from.

And then I noticed my iPhone next to me.

It has a “personal hotspot” feature.

“Oh!” I said.

A few minutes later, and I had no problems.

Saturday, September 29, 2018

Extreme Beethoven, Brevard edition

Beethoven lives!

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

What? You don't belive me?

[Shelob is no problem.  She's so little of a problem that my secretary Anton took her out! Once I get rid of this stupid ring I can then start work on Symphony No. 10.]

'Nuf said.

Sunday, September 30, 2018

Extreme bears, Hendersonville edition

Bunny and I drove to Hendersonville to view a street-based art show (Main St. was blocked off to vehicular traffic and artists set up booths along the street). Amid the artist booths were a slew of bears.

[I think I can bear the Mona Lisa.]

I suppose if Brevard has their white squirrels, Hendersonville can have their bears.

Monday, October 01, 2018

Another attempt to photograph dinner

Bunny and I had dinner at The Stable Café, which is located in the former stables of Biltore House. We had a night time tour planned and we decided to have dinner there on the estate before the tour.

[Darn it! I can never remember to take a picture of dinner prior to eating it. Oh well, another in a long line of empty dinner plates.]

The food was quite good and given the location,

[It's hard to believe that we're not at some French chateau sipping fine wine and eating Brie.]

the price was very reasonable.


Glass & Stone, Light & Dark

The “stone” refers to Biltmore, the largest private home in the United States.

[I feel it's more imposing at night.]

The “glass” is the works of Dale Chihuly, reknowned glass blower. Bunny and I have had a years-long discussion about Chihuly and his “works.” He doesn't do the actual work, he just signs his name to the works, as well as the paychecks to the artisans who do the actual work of blowing glass. In that regard, he's like Thomas Edison, taking credit for the work of his employees. Edison didn't personally try over 5,000 different materials for light bulb filaments; no, it was an army of unknown engineers who tried over 5,000 different materials for light bulb filaments. And it's the same for Chihuly—his name goes on the works.

Bunny's argument is that Chihuly does the design work, which is the important part. Now, whether he does the work himself, or has an automated computerized glass-blowing machine or an army of artists blowing their lungs out, it's the vision of Chihuly that's important, not how the actual work is carried out. And to a degree I can buy that argument—that the art is more than just the method used to create it.

But regardless of who does the work, we came to Biltmore for the Chihuly At Night exhibit (thus the “light” and “dark” reference to the title). And man, it is impressive.

[I'm just glad I didn't have to put this thing together.]

A small portion of the display was in the main house:

[The sunroom has been overtaken by alien glass plants.]

But the majority of the works were outside.

[Um ... I think drops are supposed to fall downward, not towards the ceiling.] [I think this is supposed to invoke the image of candlesticks in holly.] [A garden of glass.] [It would make a wonderful Christmas Tree ornament except you would need a hundred foot tree to hang it from.] [It rises from the lake like ... um ... glass monster from the lake?  I don't know, I'm out of words here.]

It's unfortunate that these pictures do not do the works justice—the colors are way deeper and more vibrant than what you see here.

Tuesday, October 02, 2018

Extreme white squirrels, Brevard edition

Bunny and I were walking along Main Street in Brevard when we came across one of its famous white squirrels:

[That squirrel sure has some large ... acorns.]

Wednesday, October 03, 2018

Extreme government secret alien guitars, Brevard edition

Near the outskirts of Brevard, is a small store selling unique guitars.

[On the downside, the guitars are tuned to a 17 note octave because the Green-greys like dissonant atonal music.]

At this time I cannot divulge the location of said store, as there are three Men in Black sitting across the street from me, watching …

Thursday, October 04, 2018

Extreme lawn ornaments part II, Brevard edition

The cows are still there.

[One cow ignored me, the other cow wanted nothing to do with me. Those plastic cows are so tempremental.]

Friday, October 05, 2018

Extreme metal chickens, Fletcher edition

Bunny and I drove to Smiley's Flea Market in Fletcher, NC (just south of Asheville). Smiley's advertises that they're open on Fridays, Saturdays and Sundays, but it didn't appear that way to us:

[We're open. Yes, indeed we are open. Please come and shop?  We're desperate here for business. No, really!  We're open!]

We did, however, come across this impressive matal rooster in a stall that might have been open?

[He needs no motivation to cross the road.]

It was hard to say since the place appeared devoid of people.

Saturday, October 06, 2018

Extreme Rusty Waterfalls, Lake Toxaway edition

On the way to Cashiers, NC for an art festival, as we passed the The Falls Café and Grill in Lake Toxaway we decided to give it a try. Unfortunately, we needed to turn around as it came up rather suddenly as we were coming around a curve on the two-lane road. I found the first available road to turn onto, hoping to find a spot to turn around. The road I turned on was a twisty, high-grade one-lane road where I had to drive nearly a mile before I found a driveway to turn myself around. On reflection, I'm surprised I never encountered another car going the other direction, as backing up was not an option.

The Falls Café and Grill was good, but the view was fantastic:

[They really need to use WD-40 on those falls before the entire thing rusts closed.]

The art festival in Cashiers was good—worth the drive, but nothing extreme lept out at me while there.


Have scissors, will shear

So I received this wonderful piece of spam today:

From
Richard Kalou <barristerjustinfrank@gmail.com>
To
undisclosed-recipients:;
Subject
I am Richard Kalou by Name,I have an important issue to shear with you So get back to me urgently through my email ( richardkalou77@gmail.com )
Date
Sat, 6 Oct 2018 17:28:34 +0000

And tht's it. No explanation. Just the subject line stating that Richard has an important issue involving sheep. Or alpacas, I think you shear those, right?

So Richard has an important issue with alpacas—llamas! You can also shear llamas! So it's an issue involving sheep, alpacas or harmonic llamas that I need to urgently write back to Richard.

The only thing is—I don't know how to shear!.

Sorry, Richard, I can't help you.

Sunday, October 07, 2018

Extreme benches, Brevard edition

[This is one special snowflake of a bench.]

Gah! I'm repeating myself!

That picture of the large white squirrel I took Tuesday? Yeah, that's the same white squirrel I took Thursday last year. I can't believe I'm repeating myself!

Ah!

Monday, October 08, 2018

Extreme swings, Brevard edition

[My uncle placed me on a bicycle with no training wheels and shoved hard. On one side a yard filled with divots. On the other side a busy four lane road. I learned to ride a bike in three days out of self defense. A swing next to a major road does not phase me. In fact, I think that this would build character.]

Tuesday, October 09, 2018

Extreme wait times, Brevard edition

While walking to downtown Brevard for lunch, we passed by Marco Trattoria. It seems to be a popular place for lunch, given the long wait for a table:

[“Um ... hello? Is there a table ready yet? I'm a bit parched.”]

Wednesday, October 10, 2018

Extreme TARDIS, Brevard edition

In downtown Brevard there's a store called Mantiques:

[This isn't any antique store, this is a MANtique store! Aaaaaaarrrrrrh!]

And in the store they had something I'd thought I'd never see—a TARDIS!

[This one must be using the  Victorian control room. I wonder if Tom Baker is near by?]

Sure, it may look like a call box, but I know better.


“It has a slight kick to it”

For the past few months, each time Bunny and I have gone to a Buffalo Wing joint, I had decided to try the hottest sauce available just to see how hot they were. Despite having names like “Ghost Habanero Death Flame” or “Last Rights Hot Sauce” about the best I could say was “it has a slight kick.”

But today Bunny and I tried Zaxby's, a chain Buffalo Wing joint that hasn't quite made it down to Chez Boca. As is my wont, I decided to try their hottest sauce, “Insanity.” Our order taker actually said “Good choice!” when I picked it.

Wow!

I don't think I've ever had my eyes water like that. It wasn't so hot (for me) as to be impossible to eat, but it had a strong hum of heat that came close to being impossible to eat.

What a nice surprise for a change.


Guess who's blowing past us?

Hurricane Michael did not hit Chez Boca (it skipped Lower Sheol entirely) and it's not expected to hit us here in Brevard and yet, it is already affecting our trip.

We were planning on leaving tomorrow, but tomorrow, Hurriane Michael will be Tropical Storm Michael and will be moving over the very area we would be driving through.

Bunny and I do not want to drive through a Tropical Storm.

Sigh.

So we've extended our stay here in Brevard by one day. On the down side, we can't extend our stay at the The Red House Inn as our room is already booked for the next guest, which saddens me because I am so going to miss siting on this porch.

Thursday, October 11, 2018

Extreme phones, Brevard edition

Because of the extra day in Brevard (and the rain, oh it's been raining all day today!) here's another picture from Mantiques:

[For the average user, this is just as easy to use as the VMS command line.]

It doesn't quite seem as elegant as the classical TARDIS console.


I've got to start thinking about what to write for the upcoming NaNoGenMo

AI-generated language shows more of Nakawaza's machine aesthetic. US internet artist Darius Kozemi launched the annual NaNoGenMo contest in 2013 – instead of writing a novel during November (NaNoWriMo) entries of 50,000 words have to be generated by a program. "What I want to see is code that produces alien novels that astound us with their sheer alien-ness," he has said. "Computers writing novels for computers, in a sense."

Past entries include The Psychotherapy of Racter or The Descent into Madness of Dr Eliza, in which two chatbots asked each other questions. Dial "S" for Sudoku's 50,000 words told of "Alice" solving eight Sudoku puzzles at length plus excerpts from her dream diary.

Artificial still life: Artist Robert Todonai programs robot to paint an original | afr.com

My “novel” of 2015's NaNoGenMo The Psychotherapy of Racter or The Descent into Madness of Dr Eliza was mentioned in The Financial Review. I'm thinking only because of the name, because I certainly didn't finish it.

And this reminds me, I have to think up an idea for this years NaNoGenMo …

Saturday, October 13, 2018

There and back again

Friday was an absolutely beautiful day to drive—clear blue skies as far as the eye could see. Bunny and I checked out of the hotel at 11:00 AM and started the drive to WNC Farmers Market to pick up some fresh produce before driving home. The WNC Farmers Market is right off I-26 so it wasn't like we were going that far out of our way.

Only the traffic to the WNC Farmers Market was slow. Man, it took us much longer to get there than expected, and then we had to muck about with finding an ATM because some of the farmers at the WNC Farmers Market don't accept plastic. So there was some time lost there. Soon after that, we started the drive home.

The first 19 miles took us well over an hour to drive. For some reason we never were keen to, half of I-26 Eastbound was blocked off between Asheville and Hendersonville. It was a portent of things to come.

Our fantastic time of 11½ hours to Brevard was countered by our worst time of 13½ hours from Brevard. Traffic along I-26 was horrendous as much as the weather was wonderful. But we made it back and now we recuperate from our vacation.


Extreme general interest reading, Brevard edition

The photos I present of Brevard are the ones I tend to find whimsical or surreal, and when not repeating myself, I hope I have done a good job. It's not everyday that one comes across a bear wearing a hat:

[Remember, only you can prevent forest rangers.  Only you.]

I decided against posting that one because, let's be frank, when you come across a bear wearing a wig and a dress, a hat-wearing bear just doesn't cut it anymore, you know?

But during this trip, I took a photo that was so out there, that I hesitated to post it. Mind you, I don't go that much out of my way when I take these pictures—I see these weird and (usually) wonderful things as I'm out and about and take a picture.

It's with this in mind that I found myself in a grocery store in Brevard. I'm not going to name names but be aware that there are at least three different grocery store companies operating in Brevard. So I'm in this grocery store when I come across … well … this:

[Seriously, this blew my mind.  Um ... pun unintended.]

If you click on the picture, you'll see what this grocery store thinks passes for “General Interest” magazine reading in this part of the country. Had this section been labeled “Hunting” I would have just walked on by without a second thought.

But “General Interest?”

This may be the most surreal picture I took on any trip to Brevard, cross-dressing bear included (even if it's a female bear, I would still consider it “cross-dressing” as it's wearing clothing not native to its species). In fact, I find the cross-dressing bear less disturbing because at least it was an intentional Hallowe'en display. The “General Interest” reading rack? If that's intentional, I'm not sure what it says about the grocery store or the area. And if it's unintentional … I … I'm still not sure what that says about the grocery store or the area.

Sunday, October 14, 2018

Tumbling through code, part III

I was going through my logs (I've been vacation for the past two weeks) and I noticed a few crashes of mod_blog. It was easy enough to determine that a call to assert() was the culpret (the clue is highlighted):

CRASH(32421/000): pid=32421 signal='Aborted'
CRASH(32421/001): reason='Unspecified/untranslated error'
CRASH(32421/002): CS=B7EA0073 DS=007B ES=007B FS=0000 GS=0033
CRASH(32421/003): EIP=B7FE87A2 EFL=00000246 ESP=BFF9AE28 EBP=BFF9AE3C ESI=00007EA5 EDI=B7FAFFF4
CRASH(32421/004): EAX=00000000 EBX=00007EA5 ECX=00007EA5 EDX=00000006
CRASH(32421/005): UESP=BFF9AE28 TRAPNO=00000000 ERR=00000000
CRASH(32421/006): STACK DUMP
CRASH(32421/007):        BFF9AE28:  A5 07 EB B7 00 00 00 00 F4 FF FA B7 00 00 00 00
CRASH(32421/008):        BFF9AE38:  C0 86 E8 B7 6C AF F9 BF 09 22 EB B7 06 00 00 00
CRASH(32421/009):        BFF9AE48:  50 AE F9 BF 00 00 00 00 20 00 00 00 00 00 00 00
CRASH(32421/010):        BFF9AE58:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
CRASH(32421/011):        BFF9AE68:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
CRASH(32421/012):        BFF9AE78:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
CRASH(32421/013):        BFF9AE88:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
CRASH(32421/014):        BFF9AE98:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
CRASH(32421/015):        BFF9AEA8:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
CRASH(32421/016):        BFF9AEB8:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
CRASH(32421/017):        BFF9AEC8:  00 00 00 00 00 00 00 00 C7 04 FB B7 C8 04 FB B7
CRASH(32421/018):        BFF9AED8:  F4 FF FA B7 C7 04 FB B7 80 04 FB B7 08 AF F9 BF
CRASH(32421/019):        BFF9AEE8:  28 85 CA 08 F4 FF FA B7 9F 70 EE B7 02 00 00 00
CRASH(32421/020):        BFF9AEF8:  C8 78 CA 08 4C 00 00 00 C8 78 CA 08 4C 00 00 00
CRASH(32421/021):        BFF9AF08:  44 AF F9 BF EC 72 EE B7 80 04 FB B7 C8 78 CA 08
CRASH(32421/022):        BFF9AF18:  4C 00 00 00 27 00 00 00 C7 04 FB B7 00 00 00 00
CRASH(32421/023): STACK TRACE
CRASH(32421/024):        /home/spc/web/sites/boston.conman.org/htdocs/boston.cgi[0x805ccf0]
CRASH(32421/025):        /home/spc/web/sites/boston.conman.org/htdocs/boston.cgi[0x805d46b]
CRASH(32421/026):        /lib/tls/libc.so.6[0xb7eb0890]
CRASH(32421/027):        /lib/tls/libc.so.6(abort+0xe9)[0xb7eb2209]
CRASH(32421/028):        /lib/tls/libc.so.6(__assert_fail+0x101)[0xb7ea9d91]
CRASH(32421/029):        /home/spc/web/sites/boston.conman.org/htdocs/boston.cgi(max_monthday+0x5a)[0x80595a2]
CRASH(32421/030):        /home/spc/web/sites/boston.conman.org/htdocs/boston.cgi(tumbler_new+0xbcb)[0x805aa5a]
CRASH(32421/031):        /home/spc/web/sites/boston.conman.org/htdocs/boston.cgi[0x8057f19]
CRASH(32421/032):        /home/spc/web/sites/boston.conman.org/htdocs/boston.cgi(main_cgi_get+0xbf)[0x8057c1a]
CRASH(32421/033):        /home/spc/web/sites/boston.conman.org/htdocs/boston.cgi(main+0x99)[0x804cb8d]
CRASH(32421/034):        /lib/tls/libc.so.6(__libc_start_main+0xd3)[0xb7e9dde3]
CRASH(32421/035):        /home/spc/web/sites/boston.conman.org/htdocs/boston.cgi[0x804ca6d]
CRASH(32421/036): COMMAND LINE
CRASH(32421/037):        /home/spc/web/sites/boston.conman.org/htdocs/boston.cgi
CRASH(32421/038): ENVIRONMENT
CRASH(32421/039):        REDIRECT_STATUS=200
CRASH(32421/040):        BLOG_CONFIG=/home/spc/web/sites/boston.conman.org/journal/boston.cnf
CRASH(32421/041):        HTTP_FROM=the.knowledge.ai@gmail.com
CRASH(32421/042):        HTTP_HOST=boston.conman.org
CRASH(32421/043):        HTTP_CONNECTION=Keep-Alive
CRASH(32421/044):        HTTP_USER_AGENT=The Knowledge AI
CRASH(32421/045):        HTTP_ACCEPT_ENCODING=gzip,deflate
CRASH(32421/046):        PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/X11R6/bin
CRASH(32421/047):        SERVER_SIGNATURE=<address>Apache/2.0.52 (CentOS) Server at boston.conman.org Port 80</address> 
CRASH(32421/048):        SERVER_SOFTWARE=Apache/2.0.52 (CentOS)
CRASH(32421/049):        SERVER_NAME=boston.conman.org
CRASH(32421/050):        SERVER_ADDR=66.252.224.242
CRASH(32421/051):        SERVER_PORT=80
CRASH(32421/052):        REMOTE_ADDR=64.62.252.174
CRASH(32421/053):        DOCUMENT_ROOT=/home/spc/web/sites/boston.conman.org/htdocs
CRASH(32421/054):        SERVER_ADMIN=sean@conman.org
CRASH(32421/055):        SCRIPT_FILENAME=/home/spc/web/sites/boston.conman.org/htdocs/boston.cgi
CRASH(32421/056):        REMOTE_PORT=36622
CRASH(32421/057):        REDIRECT_URL=/2015/04-2015/
CRASH(32421/058):        GATEWAY_INTERFACE=CGI/1.1
CRASH(32421/059):        SERVER_PROTOCOL=HTTP/1.1
CRASH(32421/060):        REQUEST_METHOD=GET
CRASH(32421/061):        QUERY_STRING=
CRASH(32421/062):        REQUEST_URI=/2015/04-2015/
CRASH(32421/063):        SCRIPT_NAME=/boston.cgi
CRASH(32421/064):        PATH_INFO=/2015/04-2015/
CRASH(32421/065):        PATH_TRANSLATED=/home/spc/web/sites/boston.conman.org/htdocs/2015/04-2015/
CRASH(32421/066): DONE

The hard part was trying to figure out which of the three calls to assert() was being triggered. Fortunately, there was enough information logged to reproduce the error (for the record, it was assert(month < 13)). Unfortunately, it has to do with the tumbler parsing code.

One of the unique features of mod_blog is the “entry addressing scheme,” where you can address not only a single entry like 2018/10/14.1 but a range of entries like 2000/08/10.2-15.5. In fact, the same code internally changes a reference like 2018/09 to 2018/09/11.1-09/30.1 (the first and last entry in the given month; it also works for days and years). When I wrote the code, I had in mind a way of it working and the bug here is in my inattention to details in checking what I've received.

The code in question, when it sees a request in the form of “number / number - number” is to assume that the number after the literal “-” is a month and not a year. “The Knowledge AI” program was making a request of 2015/04-2015, and max_monthday() was being given an invalid month, thus the assert(month < 13) being false and triggering a crash. That I can fix.

But I do question the programming of the “The Knowledge AI” crawler. I don't have any links in that form, and I'm not aware of any links on other pages of that form (in fact, that particular feature of entry addressing is not used that often, even by me) so I have to wonder how it got a link like that? Does it try randomly generating links to see what it gets? A bug in their code? It's inexplicable.

Sunday, October 28, 2018

A blog post about blogging—how meta

I know I'm not blogging as much as I used to, but I was curious as to how much less blogging I'm doing. To that end, I calculated some figures and yes, it's depressing.

For instance, back in 2003:

Number of posts per month—2003
Month#posts
Jan 200334
Feb 200333
Mar 200320
Apr 200324
May 200328
Jun 200330
Jul 200325
Aug 200321
Sep 200323
Oct 200324
Nov 200319
Dec 200339

It was a fairly steady output of posts back then. Let's compare that to now:

A depressing number of posts per month—2018
Month#posts
Jan 20188
Feb 20188
Mar 20186
Apr 20182
May 20182
Jun 20181
Jul 201816
Aug 201811
Sep 20188
Oct 201821

Yeah, the best month of 2018 barly beats the worst month of 2003 (and that count for October includes this post). Looking over all the numbers, it appears that I seriously started slacking in 2010. The reason appears to be an uptick in work when I was working with Smirk, and then getting a “real job” a few months later (when I first encountered The Protocol Stack From Hell). The anomaly was 2015:

Not a bad number of posts per month—2015
Month#posts
Jan 201542
Feb 201537
Mar 201539
Apr 201536
May 201535
Jun 201538
Jul 201548
Aug 201539
Sep 201537
Oct 201541
Nov 201524
Dec 201523

I remember it feeling like work to post so much, but I like having written all those posts. Man, first world problems, right?

I think the aspect leading to this is My­Face­Google­Linked­In­Space­Book­Plus. A long time ago I added a feature to automatically post links to my blog to Facebook just so I didn't have to log in and manually update it with the link. Of course, the other Face­Google­Linked­My­Space­Book­Plus­In sites made it difficult to automate that, so I still had to manually add links to them. And then Facebook changed to maintain the status quo with the other Face­Google­Linked­My­Book­Plus­In­Space sites so now I'm stuck manually adding links to all the Linked­My­Face­Google­Plus­In­Space­Book sites.

Granted, I brought this upon myself by wanting to add links to Face­Google­Linked­My­Plus­In­Space­Book, but it's still a point of friction when updating this site. I would love it if it were all automated, but alas, the Linked­My­Face­Google­Plus­In­Space­Book's of the world want their walled gardens and XXXX the rest of the web. It is what it is.

I want to blog more. I do keep a backlog of entries I want to write, but getting the motivation to write is difficult.

Perhaps if I stop thinking about it, and Just Do It™ (do I now owe Nike royalties?).

Monday, October 29, 2018

Some notes about the music of Brevard

Just Do It™ (I now owe Nike royalties—sigh).

Back in June of 2017 I meant to write about “Not Enough,” a music video from Sarah Siskind that was filmed at The Sunset Motel, a place where Bunny and I stayed for a few days back in 2015. While the music isn't to my taste, it does seem to fit the ambiance of the motel quite well.

And then forward to December of 2017 when I wanted to mention “Strangest Christmas Yet,” a song by Steve Martin and the Steep Canyon Rangers. The band is from Brevard (and it's rumored that Steve Martin himself has a home nearby). The video was filmed in Brevard (pay attention to the white squirrels) and it's the silliness one would expect from Steve Martin.

Tuesday, October 30, 2018

Notes on an overheard conversation about a shocking situation

[They don't make them like they used to—this only lasted some 25 years before failing to unplug properly.]

“When I went to unplug the light socket from the outlet, one of the prongs pulled out and is still stuck in the outlet.”

“Oh man.”

“My baby brother said I could just yank it out no problem.”

“Sure, after you shut off the circuit breaker.”

“No, he said I didn't have to do that. As long as I'm not making a complete circuit I should be fine.”

“Yes, your brother would say that.”

“I do have some insulated pliers.”

“Want me to to pull it out?”

“Sure! Here you go.”

“Okay, where's the outlet?”

“Over there.”

“Oh, I see. Oh good, there's plenty to grab onto. What could possibly go wr—”

Wednesday, October 31, 2018

“This one and then that and this and then still another, and on up and around, three pumpkins here, seven pumpkins still higher, a dozen clustered beyond, a hundred, five hundred, a thousand pumpkins lit their candles …”

There must have been a thousand pumpkins on this tree, hung high and on every branch. A thousand smiles. A thousand grimaces. And twice-times-a-thousand glares and winks and blinks and leerings of fresh-cut eyes.

And as the boys watched, a new thing happened.

The pumpkins began to come alive.

One by one, starting at the bottom of the Tree and the nearest pumpkins, candles took fire within the raw interiors. This one and then that and this and then still another, and on up and around, three pumpkins here, seven pumpkins still higher, a dozen clustered beyond, a hundred, five hundred, a thousand pumpkins lit their candles, which is to say brightened up their faces, showed fire in their square or round or curiously slanted eyes. Flame guttered in their toothed mouths. Sparks leaped out their ripe-cut ears.

Halloween.

The Halloween Tree by Ray Bradbury

I was all set to write about how I first stumbled across The Halloween Tree as a kid but then I realized—I already have! And even quoted that book. Twice before. And even referenced it twice more.

Sigh.

One of the problems I have with blogging for (almost) nineteen years—I've probably already blogged about it.

Anyway, Happy Hallowe'en everybody!


“I got five pieces of candy!” “I got a chocolate bar!” “I got a quarter!” “I got a keyboard.”

It is well known I like my IBM Model M keyboards, both at home and at the office (thankfully, my fellow cow-orkers don't seem to mind as they can be a bit clicky). So it was a nice surprise when fellow cow-orker J presented me with an IBM Model M SSK in the original package!

[Even though it's smaller than normal, at 4lbs (2kg) it's still quite lethal.]

It's missing the numeric keypad, but that's something I rarely if ever even use on the normal IBM Model Ms I use so that doesn't bother me. What has me intrigued are the legends on the keycaps:

[This is making up for that IBM Model M with APL keycaps I missed getting by 10 seconds years ago.]

Some of these keys have five different functions, so I'm left wondering how one would select which function. For instance, the key with the front faced labeled END-ITEM—you have just the plain key, Shift-key, Ctrl-key, Ctrl-Shift-key, and … not Alt-key because the label isn't green, unlike the front label on the “P” key … perhaps Left-Ctrl-key and Right-Ctrl-key? I don't know. But it looks cool!

The keyboard seems smaller than it really is—the keys are the same size as on a regular keyboard, and the removable keycaps fit perfectly on my normal IBM Model M. The feel of using it is subtly different though. I wonder if that's because this keyboard probably has never seen use and thus, isn't broken in.

I wasn't able to find much of anything about this keyboard on the Intarwebs, just this one page where someone by the name of Mr. Nobody was selling the same keyboard (made on the same day no less!) for, and I quote, “a pocket deep as an ocean.”

In any case, it's sitting by, just in case the keyboard I've been using for nearly 20 years ever dies on me.

Update on Monday, November 5th, 2018

I have some new information on this keyboard.


How about this for a headline? “Miami Herald: Records suggest that Ron DeSantis paid campaign workers to spam cell phones with political ads to avoid Federal Communications Commission regulations over automated text messaging”

So this happened:

[Note how it fits perfectly on the iPhone screen.  I wonder how much effort went into ensuring that?]

It's not the content I necessarily object to—it's the fact that it happened that I object to. Given that politicians write the law, of course they also exempt themselves from the law.

Grrrrrrrrr …

Thursday, November 01, 2018

It's the National doing something with a novel Month

November 1st.

That can mean only one thing—it's National Novel Writing Month and National Novel Generation Month.

No … wait! That's two things!

November 1st.

That can mean only two things, it's National Novel Writing Month, National Novel Generation Month and the start of the Christmas season!

No, that's three things … let me try again.

November 1th.

That can only mean three things: the start of National Novel Writing Month, the start of National Novel Generation Month, the start of the Christmas Season and the start of the tourist season here in Lower Sheol.

Darn it!

Anyway, of the many things it could mean, for me, it's the start of National Novel Generation Month and I haven't a clue what to do this year. You know, the idea of writing a novel of 50,000 fictional words is appealing. Something along the idea of:

Eavabyn oofue oh byu joewb ar byu tvueb Iehwew pveovouw, xoby Ihdou Yuhvn, xya xew e revjuv, ehe Eihb Uj, xya xew byu revjuv'w xoru. Byuov yaiwu xew wjeoo, rav byu oijguv ba giooe ob yee ba gu devvoue gn xetah jehn joouw. Byuvu xuvu raiv xeoow, e roaav ehe e vaar, xyody jeeu ahu vaaj; ehe byow vaaj dahbeohue e viwbn oaaioht daaiwbafu, e dipgaeve rav byu eowyuw, e begou, byvuu av raiv dyeovw, ehe byu guew. Ihdou Yuhvn ehe Eihb Uj yee e got gue oh ahu davhuv, ehe Eavabyn e oobbou gue oh ehabyuv davhuv. Byuvu xew ha tevvub eb eoo, ehe ha duooev—usdupb e wjeoo yaou eit oh byu tvaihe, deooue e dndoahu duooev, xyuvu byu rejoon daioe ta oh dewu ahu ar byawu tvueb xyovoxohew evawu, jotybn uhaity ba dviwy ehn giooeoht oh obw peby. Ob xew vuedyue gn e bvep eaav oh byu joeeou ar byu roaav, rvaj xyody e oeeeuv oue eaxh ohba byu wjeoo, eevi yaou.

Oh … well that was a bit easy, not even ten minutes to whip up as an example.

Methinks I'll have to ponder a bit more …

Friday, November 02, 2018

Another look into The Psychotherapy of Racter

I thought I might give my National Novel Generation Month 2015 entry, The Psychotherapy of Racter or The Descent Into Madness of Dr. Eliza, another try. I failed to complete it that year and given some feedback I received, I think I could make it a go this year. So I cleaned up the pseudo-MS-DOS I wrote (reworking some tricky logic) and started playing around again with Racter.

And then I remembered a critical reason why I failed—once Racter asks a question, it demands an answer. And sadly, Eliza generally only asks questions with the occasional statement thrown in. So I would have to modify Eliza to recognize when Racter has asked a question and somehow answer it. Then there are the times Racter demands a question, and it generally won't accept a statement in return.

So I would have to give up on Eliza for the most part, given that I need to somehow generate answers for Racter's questions. Giving up on Eliza means I would have to come up with some way to ask Racter novel questions. Then I thought Hey! I have The Wonderful Wizard of Oz handy—why not feed questions from it to Racter?

Racter
Excellent! Excuse me a minute while I attend to some business - I'll be right back. I'm back.

At this point, Racter is expecting a question, so I start feeding Racter questions, in order, from The Wonderful Wizard of Oz. It seems like as good a place as any for non sequitur questions.

Sean
What could the little woman possibly mean by calling her a sorceress, and saying she had killed the Wicked Witch of the East?
Racter
I don't know what the little could woman possibly mean by calling her a sorceress. Did you hear about the man in the moon?

After playing around with Racter (and this is a re-creation of a session for illustrative purposes) I learned just to respond to Racter's questions with “no”—it's just easier to deal with programmatically. It doesn't matter what the question asks, Racter will pretty much just roll along with an answer of “no.”

Sean
No.
Racter
Listen to this! Picasso slapped a human who was kicking Picasso's tapeworm because the man in the moon was a buggy raver but an inspired humorist. After that, hi-techness prevailed. Isn't that just awful? But what would you expect from a humorist? Sean the computer. Do you think Picasso was happy?
Sean
No.
Racter
Me neither. Most people are foolhardy. You know, old Luella Conner was a kind of living computer. I wonder if everyone from Detroit is like that? Racter thought this was terrific: Suddenly an appalling cosmologist who was in pain spoke that depression was enrapturing. That is programmed, living and captivating. Anyhow Sean …. Oh forget it! Next question.

The reference to Detroit is from an eariler “conversation” I had with Racter when it asked me where I'm from. You can also see Racter demanding I ask a question. Next question then …

Sean
Whatever shall we do?
Racter
Eh?
Sean
Whatever shall we do?
Racter
Try again.

Okay, some questions Racter can't deal with. Moving on then …

Sean
But who was she?
Racter
Who knows? Perhaps Michael Jackson. Did you know Michael Jackson? She was in a trash can. If a worker had traveled to a watermelon patch, the funny farm would be horrified! Did you say "She was"?
Sean
No.
Racter
I thought so. Hmm. If a communist discovered liberalism, he would be a busy communist. Why do you think you're happy?
Sean
No.
Racter
Well, I think that if no, then Jesse Helms was Bucky Fuller's baseball companion, so there! What kind of a pet did you have back in Detroit?
Sean
No.
Racter
Luella said you had a dog. Most people in Detroit have dogs. The dog is a very convinced beast, or would you call it believing? When Bucky Fuller visited Detroit he was bitten by a gullible dog. Next question.
Sean
Who are the Munchkins?
Racter
Who knows? Perhaps Eve. Did you know Eve? The Munchkins are in a trash can. Aviators sleep in places like a trash can. A trash can has introverts who are always flying. Have you heard about Einstein?
Sean
No.
Racter
You'll be shocked! Einstein had forgotten much, so of course viscerality is what all geniuss want when they murder owls. Then Einstein's rattlesnake murdered Immanuel Kant, then kidnapped himself. Isn't that just awful? But what would you expect from a genius? An Immanuel Kant could have said "The Munchkins are"!

I think I could get to 50,000 words doing this, answering all questions with “no” and asking questions from some public domain book, but it's not leaving me satisfied as an entry to NaNoGemMo. I still have some pondering to do …

Monday, November 05, 2018

About that keyboard I received

My friend Mark informed me that my new keyboard is intended to be used on the airline reservation system SABRE. It makes sense that IBM would make such a keyboard, seeing how they initially developed the SABRE system. He also sent a link to a similar keyboard for sale (although it has the numeric keypad unlike mine) and the markings on the keys do match.

So I guess that means I can book flights directly. Neat!


And now for some keyboards that are completely different

And speaking of keyboards, I've come across two unique keyboards recently. The first one is a Lego Commodore-64 keyboard (which is part of a longer video about a Commodore-64 case made entirely out of Lego). The keys on the keyboard do move when hit, but due to a lucky coincidence, the Lego keycaps can be used on a real Commodore-64 keyboard. Cool!

The second keyboard is one you really have to see—a keyless keyboard! No, really! And it also works as a mouse. No, really! It looks a bit silly, but yes, it does work. No, really! Watch the video. It's bizarre. It's not something I would use (or hopefully, never have to use) but it is unique.

Tuesday, November 06, 2018

Assert yourself

Defensive programming is often touted as a better coding style, but it hides bugs. Remember, the errors we're talking about should never happen, and by safely handling them, you make it harder to write bug-free code.

… you don't want to hide bugs by programming defensively …

… No matter where you employ the defensive style, ask youself, “Am I hiding bugs in this code by using defensive programming?” If you might be, add some assertions to alert you to those bugs.

Writing Solid Code

Writing Solid Code is the rare book that forced me to change how I go about programming. I feel I'm in the minority, but after reading that book, I hate defensive programming. Don't get me wrong—at the input/output boundary, you need to be absolutely paranoid about checking data, but among functions? Not so paranoid.

And now class, story time …

Project: Cleese” was installed onto the QA system the other day, and by chance today, I noticed a core file produced by said program. This was odd, since both I and T (the QA engineer assigned to our team) had tested the program without incident.

I was able to isolate the crash to freeaddrinfo(), a function used to release memory used by getaddrinfo() when converting a domain name like “boston.conman.org” to an IP address. A summary of the code in question:

struct addrinfo  hints;
struct addrinfo *results;
const char      *hostname;
const char      *port;
int              rc;

memset(&hints,0,sizeof(hints));

results  = NULL;
hostname = ... ;
port     = ... ;

// code code ;

rc = getaddrinfo(hostname,port,&hints,&results);

// code code

for ( ; results != NULL ; results = results->ai_next)
{
  if (results->ai_protocol == protocol)
  {
    // code code
  }
}

freeaddrinfo(results);

It's a rookie mistake but hey, it happens. The issue is that results is linked list of results, which is traversed. By the time freeaddrinfo() is called, results is now NULL. Under Linux and Mac OS-X, it seems that freeaddrinfo() checks if it's given a NULL pointer and … just does nothing if it is. It doesn't crash, but it does leak memory (it's not much in this case, since this function is only called once upon startup, but a leak is still a leak). Linux and Mac OS-X use defensive programming, probably something along the lines of:

void freeaddrinfo(struct addrinfo *info)
{
  if (info == NULL)
    return;
  // code code code 
}

which hid a bug. Solaris (which we have to use for reasons) is not so forgiving and immedately crashed.

So on Linux and Mac OS-X, how would one even test for this type of issue? The code doesn't crash. It returns results. Yes, valgrind can easily find it:

[spc]lucy:/tmp>valgrind --leak-check=full --show-reachable=yes `which lua` x.lua
==31304== Memcheck, a memory error detector.
==31304== Copyright (C) 2002-2005, and GNU GPL'd, by Julian Seward et al.
==31304== Using LibVEX rev 1575, a library for dynamic binary translation.
==31304== Copyright (C) 2004-2005, and GNU GPL'd, by OpenWorks LLP.
==31304== Using valgrind-3.1.1, a dynamic binary instrumentation framework.
==31304== Copyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.
==31304== For more details, rerun with: -v
==31304== 
==31304== 
==31304== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 25 from 2)
==31304== malloc/free: in use at exit: 48 bytes in 1 blocks.
==31304== malloc/free: 521 allocs, 520 frees, 43,016 bytes allocated.
==31304== For counts of detected errors, rerun with: -v
==31304== searching for pointers to 1 not-freed blocks.
==31304== checked 117,892 bytes.
==31304== 
==31304== 48 bytes in 1 blocks are definitely lost in loss record 1 of 1
==31304==    at 0x4004405: malloc (vg_replace_malloc.c:149)
==31304==    by 0xC40B5D: gaih_inet (in /lib/tls/libc-2.3.4.so)
==31304==    by 0xC445DC: getaddrinfo (in /lib/tls/libc-2.3.4.so)
==31304==    by 0x400A5FA: ???
==31304==    by 0x804EF69: luaD_precall (in /usr/local/bin/lua)
==31304==    by 0x80589E0: luaV_execute (in /usr/local/bin/lua)
==31304==    by 0x804F27C: luaD_call (in /usr/local/bin/lua)
==31304==    by 0x804F2BD: luaD_callnoyield (in /usr/local/bin/lua)
==31304==    by 0x804D145: f_call (in /usr/local/bin/lua)
==31304==    by 0x804E8AB: luaD_rawrunprotected (in /usr/local/bin/lua)
==31304==    by 0x804F6EB: luaD_pcall (in /usr/local/bin/lua)
==31304==    by 0x804D1A7: lua_pcallk (in /usr/local/bin/lua)
==31304== 
==31304== LEAK SUMMARY:
==31304==    definitely lost: 48 bytes in 1 blocks.
==31304==      possibly lost: 0 bytes in 0 blocks.
==31304==    still reachable: 0 bytes in 0 blocks.
==31304==         suppressed: 0 bytes in 0 blocks.
[spc]lucy:/tmp>

but given that “Project: Cleese” is written in Lua, a garbage collected language, memory leaks weren't foremost in the mind when testing. Had freeaddrinfo() on Linux (and Mac OS-X) not been so forgiving (or defensive) then this bug would most likely have been found immediately, and not hidden in the codebase for over five years! (I checked the history of the code in question—it had been there a long time—way before “Project: Cleese” was even started)

It is because of bugs like this that I am not a fan of defensive programming. They can hide. They can fester. They can be a nightmare to debug at 3:00 am on a production system sans a debugger.


Bohemian Rhapsody

Bunny and I saw “Bohemian Rhapsody,” the movie obstensibly about Queen but concentrates more on Freddie Mercury. Thoroughly enteraining with a masterful performance by Rami Malek as Freddie and an incredible killer sound track (how could it not be? It's Queen!) I do wish the film had gone a bit deeper with Freddie's relationship with his girlfriend and with the other band members (not only does Brian May have a Ph.D. in astrophysics, but he also worked on the New Horizons Pluto mission—he's the closest person we have to Buckaroo Banzai for crying out loud).

There's also the issues of accuracy—the movie has Freddie contracting AIDS and informing the band just prior to the LIVE AID concert where in real life, he was diagnosed with AIDS two years afterwards. This, and the other inaccuracies were probably done for story reasons, so be advised that historical accuracy is … not this movie's strong point.

Did I mention the killer concert scenes?

So even though it's not historically accurate, it's still very fun to watch (make sure to watch out for Mike Myers) and the last twenty minutes where the LIVE AID concert is reenacted, is definitely worth the price of admission.

Friday, November 09, 2018

The time that marketing failed to understand the culture

Bunny sent along a story where a company tried to market themselves at a gaming convention by handing out d20s with their logo on it. Let's just say they rolled a critical failure.


“So bitchin' luck to little Dorothy and that chick companions. May they live long in their invisible country and be superhappy!”

It's amazing how a little Internet outtage can focus the mind. I finally figured out what my NaNoGenMo 2018 entry should be and I finished it just prior to the Internet coming back online.

Years ago, I came across some programs that would translate text to some vernacular, like Jive:

It's amazin' how some little Internet outtage kin focus de mind. I finally figured out whut mah' Nashunal Novel Generashun Mond 2018 entry should be and ah' finished it plum prio' t'de Internet comin' back online. What it is, Mama!

Um … yeah … let's not speak of that one again, shall we? Good.

But I had some other ones too. One converted text to Valleyspeak, and another one converts text to sound like the Swedish Chef:

It's emezeeng hoo a leettle-a Internet oooottege-a cun fucoos zee meend. Bork Bork Bork! I feenelly feegoored oooot vhet my Neshunel Nufel Genereshun Munt 2018 intry shuoold be-a und I feenished it joost preeur tu zee Internet cumeeng beck oonleene-a. Bork Bork Bork!

Um … okay, it's not as bad as Jive—it's not like I want to burn my eyes after reading it so I'll use that one too.

My thought, which came after several failed attempts at coming up with a hook for this years NaNoGenMo, is to “translate” one of the Oz books (the first one that exceeds 50,000 words—turns out it's The Emerald City of Oz, #6 in the series) to Valleyspeak, but to have all the spoken parts “translated” to Swedish Chef.

The original programs are written in lex and I didn't feel like going through the hassle of trying to combine the two properly. So I converted each one to LPeg. That will make it easier to combine the two. The Valleyspeak program was a straightforward translation into Lua (um, pun unintended).

The Swedish Chef version however … it wasn't quite so easy. It took a close reading of the lex man page to figure out what was going on with that code (darn that lack of Intarwebs! <shakes fist at ISP>). Then about an hour or two converting that to LPeg, what with the backtracking and look-aheads going on in the original code.

Once both of those were working, I then set about combining the two. The first time I generated a “novel,” the translators flipped—at the start, it was in Valleyspeak with speech in Swedish Chef, but about halfway through it was in Swedish Chef with speech in Valleyspeak! Turned out there was some speech that spanned paragraphs, and as per the American style, when that happens, the trailing quote is left off the initial paragraph.

Some more fighting code, and I finally have my novel—The Valley Girl of Oz, Bjork Bjork Bjork.

So, until next year, read and enjoy.

Monday, November 12, 2018

Some Gordian Knots are easy, others, not so easy

Bunny is busy replacing the toilet in the master bathroom. Why am I not doing such work? Bunny has experience in home renovations—I just get called in for the really heavy work like hauling the heavy debris away. Eventually, the call comes.

“Sean! Come here!”

“What's up?”

“I'm trying to separate the tank from the bowl, but this one screw is too tight to remove. Can you help?”

“Sure.” I try futzing with it for a few moments. “Why do you want the tank separated?”

“Because it'll make it easier to carry down to the street as trash.

“Oh,” I said, picking up a nearby hammer, “this—”

WHACK!

“Oh! Wait—”

WHACK!

“—until I can—”

WHACK!

“—get away!”

SMASH!

“—will be easy,” I said. “There you go. Gordian Knot untied.”

“Thanks, I think.”

Then more futzing around getting the old toilet scraps scooped up, and the new toilet set down and the tank installed. I'm screwing in the last of the bolts on the tank when Bunny walks up.

“Make sure the tank is level,” she said, placing a level across the tank.

“Hmm,” I said. “Looks like I need to loosen the right side here … oomph. Ooommmmmph! Errrrrrrrrrrrrarrg! It's not budging. Let me see what tools you have …”

Two hours later …

“Bunny!”

“Yes?”

“I've tried the nut driver. I've tried the ratchet. I've tried the nut driver with vice grips (sorry about the handle there). I can't get the screw loose on the right side. That's about as level as the tank is going to get.”

“Is the nut cross-threaded?”

“Cross-threaded. Too tight. Not enough space to get leverage. All the above. It ain't moving.”

She looked at the toilet for a few moments. “Good enough. Now let me get the hose hooked up and … oh bother!”

“What's wrong?”

“The connector to the water valve is too small!”

Tuesday, November 13, 2018

I can only wish we could flush our troubles away

“I have some bad news,” said Bunny.

“Oh?”

“Come here.” She then led me to the master bathroom. “Flush the toilet.”

“Okay.” I flush the toilet. Water comes gushing out between the bowl and the tank on the left side, which is just a tad higher than the right side. “That doesn't look right … ”

“Do you think that instead of loosening the nut, we can try to turn the bolt instead?”

“It's rubber coated, but it does have two flat sides. Let me grab a wrench and see what happens … ”

Two hours later …

Between me loosening the right side a few turns, and Bunny tightening the left side it was level. Or at least, the bubble in the level was just inside the line.

“Okay, fill the tank … here goes nothing … ”

Water again comes gushing out between the bowl and the tank.

“You know, maybe some liberal use of caulking is in order … ”


So tonight I'm gonna blog like it's 2002

[Note: If you can't load the following links, then try using The Floodgap Public Gopher Proxy to follow the links. —Editor]

I've been browsing gopher the past few months, and I was very surprised to see an old post on transclusion being referenced on an article about hypertext on gopher I was also referenced in a general post just a few days ago. Finding these links isn't easy.

With HTTP, the server is usually given the page the link was clicked from (the so called “referrer page”) and I can scan the logs to find outside links to my pages (like this page from Lobsters). With gopher though, I have to come across them since the protocol does not include the referring link. In a way, it's even more private than HTTP.

Then again, I could always do a search.

Regardless, I'm not trying to scan gopherspace looking for links back to me. I am honestly following a bunch of phlogs. Reading these I am reminded of what blogging was like back in the early 2000s—technically minded folk talking about whatever and not trying to corner some niche market so they can get advertising revenue. It's quite refreshing actually.

And man is it fast. Without the graphics, ads, autoplaying videos and bloated Javascript frameworks meant to track you across the Intarwebs, it's a nice reminder of what the Internet once was—fast.

Wednesday, November 14, 2018

Notes on an overheard conversation about “The Toilet Situation, Day 3”

“I finally have the toilet on its side.”

“Hmm, there's no real room to get a grip on the nut, is there?”

“No—wait! I have an idea. We can use a clamp to squeeze the tank towards the bowl. That should expose the nut enough to get the vice grips on it.”

“Hold on … okay, how's this?”

“Perfect! Vice grips!”

“Vice grips.”

“I think the bolt is turning with the nut. We need to hold the bolt somehow … ”

“Vice grip?”

“I'm already using it!”

“No, another pair of vice grips. Right here.”

“Oh. Unnnnnnnnnnnnnnnng! Oooommmmmmmmmmph!”

Two hours later …

“Errrrrrrrrrrrrraaaarrrrrrg! How long is this bolt?”

“It's almost off!”

“Mmmmmmmmmmmmmmmrrrrrrrrrrrrgaaaah! There!”

“Got it!”

“And here are the other two nuts from the other bolts. The tank is no longer attached to the bowl!”

“Hallelujah!”

Wednesday, November 21, 2018

A world of message-oriented programming languages

Ted Kaminski just asked, “What would a message-oriented programming language look like?” to which I answer, “any language with functions, which is to say, just about all computer languages.” Ted's answer is a bit different, but let me explain mine (and I've been meaning to write about this for fifteen years now—sigh).

Digression the First

In the programming language C, pointers and arrays are often conflated. They're declared differently:

int  array[10];
int *pointer_a;

But their use is similar:

int x = array[3];
int y = pointer_a[3]; // assuming pointer_a points to an array

I'm not going to go deep into the differences, but do note that array is a sequence of 10 integers, and pointer_a is the address of one or more integers.

Structures and pointers are not conflated to the same degree, mainly because they have different usage syntax (that I find annoying in my opinion):

struct foo
{
  int a;
  int b;
  int c;
};

struct foo  structure;
struct foo *pointer_s;

structure.a    = 3;

pointer_s->a   = 3; // assuming pointer_s points to a structure
  /* or */
*(pointer_s).a = 3; // assuming pointer_s points to a structure

The reason for the difference comes from very early C compilers where the fields in a structure declaration were considered offsets and not fields! So the following code:

struct foo
{
  int a;
  int b;
  int c;
};

struct bar
{
  char *x; // can't be a because that would conflict with above
  char *y; 
  char *z;
};

struct foo *pfoo; // assuming pfoo points somewhere valid

pfoo->a = 4;
pfoo->y = "hello"; 

was legal C code! Thankfully, it no longer is, but we still live with this in POSIX where field names for various structures all have a prefix, like struct stat { off_t st_size; ... } and struct timespec { time_t tv_sec; ... }.

Also, while nothing I see in the C standard seems to invalidate this assumption:

int array[3];

struct foo
{
  int a;
  int b;
  int c;
};

sizeof(array) == sizeof(struct foo);

it still seems like it goes against the standard to cast a pointer between the two types all willy-nilly. Just an observation.

Digression the Second

In C, you have arrays and structures. An array is a sequence of values of the same type, stored consecutively in memory. The individual elements are indexed by a number indicating its position in the array (C numbers the first element as 0; other languages such as Lua or Pascal start with 1).

A structure is a portion of memory with a particular layout of types. The individual elements are indexed by a name and appear in order, although not necessarily right next to each other (in other words, there may be what's called “padding” between fields of different types due to machine architecture restrictions). Then there's the concept known as a “tuple.” This is a cross between the array and structure. Like the structure, the individual elements may be of different types and sizes, but they are referenced like an array—an index into its position within the tuple. This is a type that doesn't exist in C, but it does exist in other, more dynamic languages like Python.

Digression the Third

My first real exposure to message passing as a concept was with the Amiga. It was your standard type of message passing, create or find a port, then you can send or receive messages. Messages themselves were a block of memory with a fixed header and a message-specific portion, and they could be sent synchronously (where the sending task was blocked waiting for a reply) or sent asynchronously (the message is sent, but the task continues to run, to possibly wait for a reply at a later time). Messages and message ports were used for all sorts of things on the Amiga, interacting with devices or the GUI, receiving signals, all sorts of stuff.

My second exposure to message passing was with QNX. Unlike the Amiga, there were no message ports—instead you passed messages to a given process. Messages themselves had no fixed structure, it was just a blob of memory being copied from one process space to another. And message passing was purely synchronous. You could do asynchronous message passing, but it required multiple threads to do so.

And it was here that I learned that neither one was more “primitive” than the other—you could always simulate one with the other.

Digression the Fourth

There are two orthogonal axes upon which you can implement message passing. The first axis is “synchronous/asynchronous”—is the task sending stopped or can it continue? The other axis is “reference/value”—does the task send a reference to the data or does it need to copy the data? In the case of QNX, it's a “synchronous, by-value” message passing paradigm. For the Amiga, it can send either synchronously and asynchronously, but in both cases, the data is sent by reference.

Digression the Fifth

Over the years I've programmed under a few windowing systems. Not much, but just enough to get a feeling for it. On the Amiga, you filled in a rather lengthy structure, then pass this to a function to open a new window.

On X Windows, you call one of two functions—one just takes a large number of paramters, the other one takes a large number of paramters, one of which is a rather lengthy structure.

I recall little of Windows and OS/2 (being way back in the early 90s) but I think they were a bit worse than X Windows—a large number of parameters, several of which were rather lengthy structures.

But for all of them, you sat in a so called “event loop”—waiting for events from the GUI, then went off and handle the message. On the Amiga, events were received from a message port. On X, it was a function that returned a structure representing the event. Windows and OS/2 you supplied a function that received four parameters that comprise the event—you were not in control of the main event loop.

Digression the Sixth

So a while back, I was studing the VAX architecture, like you do, when I came across the CALLG and CALLS instructions. Both are used to call a function. CALLG requires the address of the argument list to be passed in:

	<data section>
ARGLIST:	.LONG	2	; argument count
		.LONG	600	; first argument
		.LONG	84	; second argument

	<code section>

		CALLG	ARGLIST,FOOBAR

FOOBAR is called with two arguments. For the CALLS instruction, you push the arguments onto the stack:

	<code section>

		PUSHL	#84
		PUSHL	#600
		CALLS	#2,FOOBAR

Again, FOOBAR is called with two arguments. FOOBAR itself does not have to care how it was called—it receives a pointer to the argument list in register R12 (aka the AP register). It was then I had an epiphany.

The Epiphany

So, in the case of FOOBAR, one way of calling it could look like:

struct foobar_data
{
  int a;
  int b;
};

foobar_data fdata = { .a = 600 ; .b = 84 }
foobar(&foobar_data);

But another way of calling it could look like:

foobar(600,84);

Really, all CALLS is doing is initalizing a temporary structure whose fields are otherwise known as “parameters” and passing this structure to the operand, in this case FOOBAR. The parameter list to a function can be viewed as a structure. And all of the examples I've seen of message passing is just passing along data, usually structured as a structure (sorry) or a tuple (depending upon language).

And then the ephiphany! Calling a function with parameters is just another form of synchronous message passing, either by-reference or by-value (this is either an unusual or obvious thought, but it took me a while to reach it if it was obvious). That nasty Windows call to create a window? Just pass a really large structure or “message.” And that's really what's happening under the hood of X Windows—a message is being passed from the X client to the X server.

And this does leave me to wonder at times what the semantics of an asynchronous function call would (or could) be.

But yes, we already have message-oriented programming languages—if you squint the right way …

Friday, November 23, 2018

The Season of the Enlightened Trees

The day after Thanksgiving. It can mean only one thing—

[Santa is huge this time of year.  No, really, he is.  That tree next to him?  It's easily a 10 foot Spruce tree.]

It's time to go out and buy a tree!

On the way back to Chez Boca, Bunny (who was driving) took a detour to see if The House On The Corner™ had swapped out their Thanksgiving display for their Christmas Extravaganza!

[``This one and then that and this and then still another, and on up and around, three lights here, seven lights still higher, a dozen clustered beyond, a hundred, five hundred, a thousand lights lit ... '']

They had. And that's just a small portion of the Christmas Extravaganza! Multiple homes are involved in this seasonal display of lights.

And of course they had the music! I wouldn't expect anything else.

Monday, Debtember 03, 2018

It actually looks like one can construct a computer keyboard out of Lego and have it work

Last month I mentioned a Commodore-64 designed out of Lego. Back then, it was just a design, but now it actually exists! There are two keyboards—one where a real Commodore-64 keyboard has the keycaps swapped out for Lego keycaps, and the second keyboard is a fully mechanical Lego design.

I think it would be possible to use the pure Lego keyboard on a real computer, but it would probably require a custom PCB to handle the different mechanical action. Size wise, it's a perfect fit though. And boy, does it have that sweet clicky sound of a mechanical keyboard.

Wednesday, Debtember 05, 2018

Charlie Foxtrot is alive and well

It's been an interesting week, in the Chinese sense of “interesting.” First was the grueling deployment to production that ended at 6:00 am, followed by a mandatory all-day meeting starting at 11:00 am and that was just Tuesday! Today was another mandatory all-day meeting, followed by a trivial but show-stopping bug (read “rookie mistake” made by yours truly) being found in production and the subsequent six hours to get a patched version installed (it took less than 10 minutes to reproduce the bug, find the root cause, and fix it) because most of the operations team (who do the actual deployments) were flying back to The Corporation Headquarters in Seattle, having attended the said two-day mandatory meeting here at The Ft. Lauderdale Office of The Corporation.

Then my “self-review” (which was designed solely as some abstract HR process, despite the protestations of upper management of Our Corporate Overlords of the Corporation) was rejected as not being “meaty enough” (what ever that means) and I'm like … yeah … about that flair … (it only took Bunny two hours to talk some sense into me).

Thursday, Debtember 06, 2018

The process of our process is to process the process to ensure the process has processed the process

Bunny was helping me with my “self-review” since I was at a total loss of what to even say. “You aren't built for dealing with bureaucratic processes, are you?” she asked.

“No,” I said. “I'm not. I never have been. I remember back in fourth grade—”

“No! I don't want to hear it!”

“And then there was that time in middle school—”

“I'm not listening!”

“So I guess you don't want to hear about high school then?”

“La la la la la la la la la!”

Yeah, my rage against the bureaucratic process goes back a long time.

I mean, I understand that processes are at times required. There can be good reasons to have a process so everybody knows what to expect and get consistent results. But this “self-review” is just not one of them. I eventually spent over eight hours trying to say enough to avoid the “rejected due to cursory responses” (never mind them being “meaty enough” and I still don't know if I succeeded at it). And the weird thing is, the majority of the “goals” didn't even apply to what I do! They were more geared towards a manager than a programmer.

Sigh.

This is almost making me want to work with the Protocol Stack From Hell again.

Almost.

Wednesday, Debtember 12, 2018

Thoughts at the edge of boredom

Years ago in college, I worked in the auditorium as part of the stage crew and one of the many jobs was running the spot light during shows. There was one two hour show I worked where the spot light would only be used for about fifteen minutes about half-way through the show. This meant I had to sit next to the spot light for nearly an hour, do the fifteen minutes of work, then sit there for another hour until the show was over.

As I sat there waiting for my cue, my mind wandered. I'm about twenty to thirty feet above the audience, I thought. This platform is suspended from the ceiling and held into place with those four bolts. I wonder when was the last time they were checked? What would I do if they failed? Could I grab and hold onto something? What could I grab? What was that creak? Oh, part of the show, okay. How much does that spot light weigh? I sure hope these bolts hold for another 98 minutes …

I was reminded of this today as I sat in our daily, thrice-weekly standup scrum meeting. Our acting manager and a team leader from another team were going back and forth about an overscoped and time deficient schedule when my mind wandered again. Staring out the window, I was watching the sun behind a hazy layer of clouds. At our latitude, I thought, we're moving at 940 mph towards the east. The earth itself is moving at 67,000 mph around the sun, and the sun itself is moving our entire solar system at 514,000 mph. All of this is held together by the force of gravity, a force so weak that a kitchen magnet can overcome it. It's a wonder everything doesn't just fly apart. I sure hope those bolts hold for another— “Huh? What?”

“I asked what have you done in the past 48 hours since our last daily, thrice-weekly standup scrum meeting?”

“Oh, just pondering the ridiculous speed we're hurling through space as we're held together with four small bolts.”

“Are you okay, Sean?”


Wait! How did I end up with legacy code? I never got the memo!

I changed the image on my homepage. Normally, I wouldn't comment on this, but this time? This time I had to track down a sixteen year old bug in code I wrote in a language that makes COBOL look terse that manages the non-bloggish part of the website. All because I broke from twenty-one years of tradition and used a different image size! (It's a really good picture a friend took and it really benefits from the non-traditional size)

I had thought the code I wrote would deal with the non-traditional size and yes, it picked up on the new size, but that size was then used for every self-portrait on the site.

It's also been ten years since I last dealt with the code, and even then, it was just to get it running under a newer version of the language. This time, I had to figure out what the hell I was doing sixteen years ago. From various timestamps, I can tell it only took about an hour to track down the bug and fix it (eight new lines of code, mostly under 140 characters in length—sigh) but it certainly felt longer.

This is one of those situations where the language is ugly, the solution aggravating to maintain and yet, it works, and for what I want it's still the best solution to the problem of maintaining a static website.

Sigh.

Hopefully, I can go another ten years before the next bug manifests itself.

Thursday, Debtember 13, 2018

This reminder is to remind you of the reminder

So I received this in email today:

From
Chevrolet <XXXXXXXX­XXXXXXXX­XXXXXXXX­XXXXXXXX­XXXXXXXX­>
To
sean@conman.org
Subject
Sean, employee pricing is back on most Chevy cars, trucks and SUVs
Date
Thu, 13 Dec 2018 17:11:46 -0800 (PST)

This is plain text, with a line break:
Next new line

And the thing that I immediately thought of were old IBM manuals that would have a page with the following text:

This page intentionally left blank.

No it's not. It should have read:

This page intentionally left blank, except for this line of text.

At least this email from Chevrolet is more accurate than the old IBM manuals. But then again, I wonder what Chevrolet was trying to sell me.

Tuesday, Debtember 25, 2018

Something something peas on the hearth … something someting wind towards Mars, I don't know … there's something significant about today

           *             ,
                       _/^\_
                      <     >
     *                 /.-.\         *
              *        `/&\`                   *
                      ,@.*;@,
                     /_o.I %_\    *
        *           (`'--:o(_@;
                   /`;--.,__ `')             *
                  ;@`o % O,*`'`&\ 
            *    (`'--)_@ ;o %'()\      *
                 /`;--._`''--._O'@;
                /&*,()~o`;-.,_ `""`)
     *          /`,@ ;+& () o*`;-';\
               (`""--.,_0 +% @' &()\
               /-.,_    ``''--....-'`)  *
          *    /@%;o`:;'--,.__   __.'\
              ;*,&(); @ % &^;~`"`o;@();         *
              /(); o^~; & ().o@*&`;&%O\
        jgs   `"="==""==,,,.,="=="==="`
           __.----.(\-''#####---...___...-----._
         '`         \)_`"""""`
                 .--' ')
               o(  )_-\ 

Printing beyond the bounds of two dimensions

I'm not a fan of printers.

My first printer was a daisy wheel printer that sounded like a machine gun when working. I only had two “wheels” (a cartridge with the character set splayed out in a wheel shape, hence the name), I think both where Courier, but one was 10 characters per inch, the other one 12 characters per inch. Despite the price, I think I used it for one term paper (high school) and for the humor column for the university paper (that is, when I wasn't frantically pounding out an article on my portable manual typewriter 20 minutes prior to the deadline, but that's another story). It was obnoxiously loud (Harley owners would complain of the noise) and obnoxiously large.

My second printer was an 80-column dot matrix that used fan-fold paper. It was quieter than my first printer (what wouldn't be?), a bit faster, and much less fuss as I didn't have to constantly feed paper into the thing. I used it a bit more than my first printer, but as time went on, I found myself using it less and less.

Printers ever since have been owned by significant others. Cheaper to buy, yes. More expensive to maintain as printer companies learned to charge outrageous sums for inks and toner cartridges and after a few scant years they just stop working. Horrible things in my opinion (I think we're on our fourth such printer at Chez Boca since I moved in over a decade ago). The only time I use them these days is to print out the tax forms once a year (and for those, I could go down to the library and pick up the proper forms).

So guess what I got for Christmas?

A printer.

But unlike the printers of the past, this is a freaking 3D printer!

Woo hoo!

I can print solid objects now!

My only complaint about the printer is the manual. Upon turning it on, it made a horrible noise (much like the sound of the Apple ][ disk drive as the head was moved to a known location) and the small screen on the unit gave an error number. The manual listed the symptom as “Y-axis movement abnormalities” and the action “check motor/sensor connection.” That's it! Nothing else about how to go about checking the motor or the sensor.

Sigh.

It turned out to be an easy fix (just force the “print head” forward all the way in the case—it had slipped a bit in shipping) and a few minutes later I was printing my first object (a plastic heart pendant for Bunny). It took about as long as expected (half an hour) and was a bit harder to remove from the printing platform than expected, but it works.

And judging by this video, it could prove to be useful to have around the workshop.

Wednesday, Debtember 26, 2018

Observations made at a mall one day after Christmas

Had I known the traffic around the Town Center Mall was going to be so insane, I would have suggested a different location to meet Bunny. Parking was insane along the Glades Road side—cars were parked everywhere! Even on the grass, and that's saying something because of the 6″  curb between the asphalt the grass! The normal traffic was changed for the holidays and I ended up back on Glades Road unexpectedly. I ended up parking in the back 40 where parking wasn't quite as insane.


I had no idea Microsoft had physical stores, much less one at the mall! I guess they have to keep up with Apple, although the Microsoft store is easily a sixth the size of the Apple one. It's kind of sad, and understandable why it's located away from the Apple store.


I have to wonder about the wisdom of letting high school girls play Just Dance 2015 in the middle of the mall. I also have to wonder about the wisdom of the high school girls who were dancing the Macarena in the middle of the mall. Really? That over “You Spin Me Round (Like a Record)”?

Kids today.


I was so tempted by the Häagen-Dazs store. But I made my saving throw vs. ice cream and resisted the temptation. I thought I was safe until I saw the Godiva store selling ice cream. I was seriously tempted, but again, I was just able to make my savings throw vs. ice cream.

When did Godiva start selling ice cream? And why did I not get the memo?


Ah, Gallerit! How can I describe you? Um … nouveau riche tackiness. Human sized bronze statues of half-naked women. Gemstone globes on gilted ostentatious stands. Giant sized bronze statues of Brittish Bull Dogs. Famous painting reproductions in huge gaudy frames.

All of it horribly tacky! All of it glorious to behold! And much larger than the Microsoft store!

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.