Kai MacTane’s Software

Feedback: If you discover bugs in any of my software, or want to send me comments, or you've found some great new way to use some of my stuff, please feel free to let me know about it.

Social Software Tools

As a some-time blogger, online journaler, and Twitter user, I wind up using a fair bit of social software. Occasionally, I either write some of my own, or make contributions that are intended to help existing works.


I started this project when I realized that many of the existing “show my latest few tweets on my blog” packages just didn’t do what I wanted and needed. Hummingbird is small, lightweight, and can easily be made quite pretty. In addition, I think it’s reasonably feature-rich (if I do say so myself).

The Hummingbird project home page will tell you how to install and configure it, and has a list of features.

System Administration Tools

Although I no longer work professionally as a system administrator, I still have to administer my own system. As a result, I occasionally wind up writing software to make system administration easier.


If you run a publicly-accessible SSH server, you’ve been fielding dictionary attacks. As long as you don’t have easily-guessed passwords on any of your standard-named accounts, this is merely a nuisance instead of a real security risk — but it is still a nuisance. If nothing else, it bloats your log files, making it harder to find anything else amid all the "failed password" lines.

The SSHblock project home page includes a full description, documentation, download link, and licensing information.


In my Copious Free Time, I'm teaching myself Japanese. In the process of doing so, I've also wound up writing some tools to help me. If you're learning Japanese too, you might also find them useful.

Kana Drill

This was loosely inspired by Mark Rosenfelder's Kana Flash Cards, but is based around two major changes from Rosenfelder’s idea: First, my Kana Drill works at the level of entire words, rather than individual glyphs. Second, it allows you to focus on the items you already know, rather than omitting them like Rosenfelder's flash cards. My guess is that each system is useful to a different group of learners, based on different learning styles.

In addition, I developed the first version of this tool when I was learning the Prototype JS framework, and used it as a venue to understand some of Prototype’s features and general ways of doing things.

My hiragana/katakana Kana Drill page assumes you have East Asian language support installed; without it, you're likely to see a lot of little hollow boxes or question marks.


The following libraries are things I've written over the years, generally to scratch some particular itch. The safeopen() function, in particular, is one that I still paste into other projects occasionally when I need it. These libraries are released under a Creative Commons license; see the end of the page for details.

safeopen() PHP Library

A single function, written in PHP, that opens a file safely for reading or writing, providing file locking and error reporting. If the file you attempt to open is locked, safeopen() will automatically retry it every X milliseconds until Y seconds have passed, then time out. You can set X and Y by altering a pair of variables declared at the beginning of the function. By default, the retry frequency is 250 milliseconds, and the final timeout is 5 seconds.

Rationale: If you fail to acquire a file lock in a web server situation, it's probably because some other server process or thread was using it. But that other process or thread will probably be done with the file in under a second. There's no need to show the user a "Could not acquire file lock" error message; instead, just retry a few times, until you can show the user a successful response — even if it's a second or two later.


resource safeopen ( string filename, string error_msg [, string filemode, int lockmode ] )
Will attempt to open the file named by $filename, then flock() it, retrying until it succeeds or the timeout delay elapses. Returns a filehandle resource on success; on failure, it will return false and put an error message into the $error_msg variable. By default, files are opened for reading only and the lock mode is exclusive (LOCK_EX). The $filemode variable will take any standard fopen() mode as its argument, and the $lockmode variable will take any standard flock() locking operation.

Lock operations automatically have LOCK_NB added to them, so it’s unnecessary to add that to the $lockmode. This allows safeopen() to abort after the timeout limit is reached, rather than blocking indefinitely.


This function has been tested and deployed on Linux, and works fine there. On Solaris, some work may be needed. At a bare minimum, you'll have to add the -l permission to the file’s mode before it can accept an exclusive lock (man -s 2 chmod or man flock for details). It has not yet been tested on FreeBSD or other Unices.


You could add this function to a library or other PHP file that you’re already include()ing in your script, or just copy-and-paste the entire thing into your script.


view source code
download function (safeopen.php)

libdirbrowser AJAX Library

This library implements an entire AJAX-based directory browser, which can be displayed on a web page using a <select> form element of whatever size you desire. The page that includes the <select> element simply needs to include a single JavaScript file; this contains routines that will contact a server-side script and retrieve directory listings. The download package includes a server-side script in PHP to handle the AJAX requests.

This is something I built when I was first teaching myself how to do AJAX coding, back in the summer of 2005. Note that this library predates the popularity of JavaScript frameworks like Prototype, jQuery, and so on, and includes its own XmlHttpRequest wrappers. The documentation talks about setting up an onLoad handler. Nowadays, of course, I'd just build on top of something like jQuery and use a $(document).ready(); call instead. However, the library still works smoothly alongside modern techniques.


While there are nearly a dozen functions in this library, only two should ever be called from outside the library itself. For full descriptions and calling syntax for those two functions, use the button to the right. If you want to investigate all the library internals, please read the source code.


For full installation and usage instructions, see the README.txt file in the Zip download file, below. Abbreviated version: put the .js library and associated PHP script on your server, editing options to configure; then set up an HTML page including a form and a pair of JavaScript event handlers.


If you’d like, you can see a version of libdirbrowser in action. The libdirbrowser demonstration page will allow you to browse around the directories on my own personal site, and submit a value to a debugging script.


view JavaScript library source code
view server-side PHP module source code
Full download: contains installation instructions, documentation, client-side JavaScript library, server-side PHP script, sample/demo HTML page showing usage, and two GIFs for enhanced display on Gecko-based browsers: (libdirbrowser.zip)


Creative Commons LicenseThe libdirbrowser library and safeopen() function are licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 2.5 License. Please feel free to study them, to use them in your non-commercial web site, and to develop other (non-commercial) libraries and applications based on them. Please don’t be too worried about the “non-commercial” aspect of this license, either. I’m not at all opposed to people using my work commercially, I’d simply like the opportunity for royalties if you think you’re going to make a lot of money. Please contact me before using these libraries commercially; I’m willing to work out very reasonable licensing terms.

Archived Software

My ancient, no-longer-supported stuff includes mlm-command and QuizMaster. If you really want to look at either of those older packages, please check in the archived software directory.