January 26, 2005

automating process shutdown with bash

Often you want to capture the pid of a process you're starting in the background so you can shut it down later in an automated way. You'll see a lot of complicated scripts that grep or awk through the output of ps, but all you really need to know is the special bash/sh variable $!.

The $! variable stores the pid of the last backgrounded process. So, start your process with an ampersand, and then echo $! to a pidfile somewhere.

Posted by Alan at 11:46 AM | Comments (0)

January 24, 2005

ntfs sshd_server permissions

A minor blip regarding cygwin sshd setup on an ntfs machine: you need to give the sshd_server account read & list directory contents access to your .ssh folder, and read access to the authorized_keys file beneath. Otherwise pubkey authentication is not going to work, and it will not at all be apparent why.

Posted by Alan at 02:03 PM | Comments (0)

January 10, 2005

portable textmode games (long)

I am certain that no one but me will find this particular post interesting. That said, read on...

Textmode games are great. I blogged about starting one in Perl last year, but that entry was unfortunately lost in The Great Crash. To make a long story short I was messing around with libcaca, an ascii art library that has pretty impressive portability (it can link against ncurses, slang, X11, and DOS's conio.h). Without too much difficulty I built a perl wrapper for libcaca with swig.

Now, to many old school folks, textmode games connotate roguelikes which restrict themselves to the "printable" region of the ascii character set. E.g., you are a little @ sign running around fighting p's and o's.

I grew up into a different tradition. We had an IBM PC XT. Most of the games I wrote growing up made full use of the entire IBM PC character set, which includes graphics like little smiley faces and blocks with holes in them (perfect for locked doors). I'd love to use that character set again in a game...you know, sort of pick up where I left off, before I got distracted by college and forays into graphical programming.
PC character set games have a rich tradition of their own. There's the Kingdom of Kroz series by Scott Miller, whose Apogee Games went on to produce Wolfenstein 3D and Duke Nukem. Or ZZT, which was the first release from Epic Megagames.

Unfortunately, practicioners of the PC character set game typically have to throw portability to the four winds. These games only run under DOS. Even Windows itself may have problems running them. Throwing portability to the four winds is not something I'm capable of doing anymore; my programmer's conscience just doesn't allow it.

For the past few weeks I've been investigating ways to get the whole PC character set to display on Free OSes. My first experiments were with libcaca's x11 driver. I found a little tarball somewhere with 6x8, 8x8, and 8x12 versions of the ibm cp437 font for X. I added these to my X font path and, voila, got my hands on the full PC character in an X window.

But I wasn't quite satisfied. The font was pretty small in these X windows. Attempts to enlarge it with the Gimp led to pretty crappy-looking characters that I knew I'd have to retouch bit-by-bit. Besides, nothing beats the immersive experience of playing a textmode game in a full-screen console.

This turned out to be a lot trickier, because I suddenly had to deal with terminals which wanted to interpret some of these characters I was trying to display as escape sequences / control codes. A full week of digging through the source to the Linux console driver, FreeBSD's syscons and pcvt drivers, cygwin's fhandler_console code, various ansi standards and ancient vt100 manuals has convinced me: terminals are the cruftiest thing on the planet. No matter what I've said about other technologies (c.f. email) with high levels of cruftiness, terminals and consoles take the cake.

This thread on comp.os.qnx got me pretty far. Using the "ESC [ 3h" escape sequence, you can tell your console to display control characters. On both cygwin terminals and FreeBSD syscons consoles, this trick got everything except characters in the range 0x07-0x0d and 0x0f to display. If these weren't some of the neatest PC characters out there, I would have settled.

At my wit's end, I posted to the bug-ncurses mailing list, and got a prompt response.

If you're on a Linux console, the easiest thing to do is to put the console in UTF-8 mode, and then display the characters 0xF000 through 0xF0FF. These special Unicode characters always map to the physical characters in the current console font. Here's a short Perl script:
#!/usr/bin/perl -w

print "\e\%G";   # select utf-8 mode

for (0x00..0xFF) {
    printf "%02X: ", $_;
    print chr(0xEF),
          chr(0x80 | ($_ >> 6)),
          chr(0x80 | ($_ & 0x3F));
    print $_ % 8 == 7 ? "\n" : "   ";
}

print "\e\%@";   # select iso mode

Not having access to a Linux box, I downloaded Knoppix and ran the script. Sure enough, it worked: all 256 characters displayed.

Now, at the time of this writing at least, Linux is not my favorite OS. I do most of my stuff under FreeBSD. I wondered if the same thing that worked under the linux console would work under syscons.

Unfortunately, the answer appears to be no. syscons does not support a special UTF-8 mode. I decided to look for another way.

Reading through the consio.h source code, I became aware of a screen map buffer that translates character codes before they are displayed on screen; this screen map is used in I18N in fact. Maybe I could map a few PC characters I didn't care about onto the ones I did!

The vidcontrol utility can dump and load screen maps. However, the dump format differs from the load format, and I could find no userland documentation on what the screenmap (scm) format actually was. Poking around under src/share/syscons/scrnmaps in the source tree, I discovered that it is simply a 256 character long table that is base 16 encoded with uuencode.

So I built a new screenmap, loaded it with vidcontrol, and it worked.

What a mess eh? At this point it would almost be preferable to do the same screen map thing under the linux console, or use the above linux console hint in conjunction with a locale setting under FreeBSD, for the sake of consistency.

Another looming problem is that these console hacks will probably not work with libcaca. caca_putchar only takes a char argument. In order to get the ascii graphics characters to display at all you need to use the ncurses A_ALTCHARSET flag OR'ed with the character, which produces a 2 byte code. At the moment I see no way to get the A_ALTCHARSET flag in there with libcaca. So I may end up pulling the interesting parts of libcaca into my own library. There are certainly things in there I don't want or need: slang support, and functions to render ascii art, to name a couple.

Posted by Alan at 01:37 AM | Comments (1)