29 May 2006

A funny "Stylish" style sheet

My girl friend is learning Java and browsing the apis a lot. Lately she complained that it should be possible to just see the classes and interfaces you have already visited in the lower left frame, because it often happens that you need to visit the same class more than once and it makes searching in those thousands and thousands of classes easier. So I thought that that should be fairly easy and started looking around. Then I found Stylish, a Firefox extension similar to GreaseMonkey but for CSS instead of JavaScript. I wrote the following style:

@namespace url(http://www.w3.org/1999/xhtml);

@-moz-document url(http://java.sun.com/j2se/1.5.0/docs/api/allclasses-frame.html) {
a {
display: none !important;
a:visited {
display: inline !important;
br {
display: none !important;
td {
white-space: normal !important;

@-moz-document url-prefix(http://java.sun.com/j2se/1.5.0/docs/api) {

Note the seemingly useless second part that applies the empty ruleset to all pages under the apis hierarchy. It's there to make sure that you can turn it on and off with just a two clicks: Stylish otherwise doesn't put it into its popup menu.

16 May 2006

A small program by the name of svn-notify

I wrote a small and very simple Python program, svn-notify. If you run it, it checks which files in the given directory are modified or added, and if there are any changes, it asks Subversion what it thinks of them. If they are considered a committable change, then the user is notified of the change. The program is so amazingly unadvanced that you have to start it in the directory where it is located, otherwise it can't find the two images it needs to display.

I sometimes tend to forget that I still need to commit my changes to the repository, so I hope that this helps to remind me.

My python script for ssh blacklisting

I recently started seeing some people attempt to brute-force their way into my SSH daemon. This is not really a risk, because only one account is accessible from the outside and its password is good enough, but I still didn't see why this should be allowed. So I installed BlinkEye's blacklist.py to stop it. This worked fine in practice, but I didn't see why it would be necessary to poll for the log lines and also why the dependancy on logtail was necessary. Especially since syslog-ng has this wonderful feature where you have a program as destination, and syslog-ng feeds the output line-by-line to the program. So I wrote ssh-blacklist.py.

Some simple performance tests very similar to BlinkEye's seem to show that it's in the same order of magnitude of speed as the original; it read and parsed the pre-generated log-file (line by line!) in 15 seconds (wall time) on a Pentium IV 3 Ghz. I did cheat a bit here, because I ran it as non-root and changed running the iptables commands into just printing the commands. But I guess this does not impact performance all that much; they were printed and rendered to an xterm, so that's not so lightweight either.

In order to use the script, you need to be running syslog-ng. Add a section similar to the following to your syslog-ng.conf:

# ssh blacklisting program
# this will open the given program and feed it the given lines one by one
destination dpr_blacklist {program ("/usr/local/bin/ssh-blacklist.py"); };

log {
source (s_all);
filter (f_auth);
destination (dpr_blacklist);

Here, f_auth is a filter that filters out anything but the auth and authpriv facilities. It is standard on Debian.


  • Change the commands.* stuff into os.spawn*. We don't need the output of most commands anyway.
  • Make the position at which we jump from the input chain to our custom chain a configurable variable.

You can view the script here.

Some of my LaTeX tricks

Every mathematician of the last 20 years should have their personal bag of LaTeX tricks. Here's a couple of mine:

  • Graphics. This, in particular, is an area where everyone has their own tricks. My standard procedure is as follows:
    • Create some graphic in XFig, making sure that all text is marked special. (You can do this automatically by editing your .xfigrc file.)
    • Using TransFig, convert this file into four formats: pstex, pstex_t, pdftex, pdftex_t. There's a catch here: you need to make sure that myfigure.pdftex_t version includes myfigure.pdf, not myfigure.pdftex, which is the default. I guess this counts as a bug. This chore is usually done by a script for me:
      # Convert all fig files to four other formats, using fig2dev.
      for FILE in *.fig; do
      FILE=`basename $FILE .fig`
      if [ $FILE.fig -nt $FILE.pstex ]; then
      fig2dev -L pstex $FILE.fig $FILE.pstex
      if [ $FILE.fig -nt $FILE.pstex_t ]; then
      fig2dev -L pstex_t -p $FILE.pstex $FILE.fig $FILE.pstex_t
      if [ $FILE.fig -nt $FILE.pdf ]; then
      fig2dev -L pdftex $FILE.fig $FILE.pdf
      if [ $FILE.fig -nt $FILE.pdftex_t ]; then
      fig2dev -L pdftex_t -p $FILE.pdf $FILE.fig $FILE.pdftex_t
    • Then in my LaTeX file, I have this code in the preamble:
      and whenever I want to include the file myfigure.fig, I just write \myinput{myfigure}.
    This has several nice properties: you can use LaTeX math constructs in figures (just surround them with dollar signs) and it looks great in both PDF and DVI.
  • I'm very proud of the following piece of code:
    \newcounter{storedequation} % To store the equation number when we
    % temporarily change it.
    Now we have an environment lettereqns, with one parameter, which makes all equations in it be numbered (P1), (P2) etcetera if the parameter is P.

On the subtle interplay of GRUB and FreeBSD

I installed FreeBSD on one of my home computers and was puzzled why GRUB wouldn't boot it. In particular, I found that you typically had to type a stanza like this:

title FreeBSD 6.0
root (hd0,3,a)
kernel /boot/loader

However, when I did this, it would work only partially. The FreeBSD boot loader would load, but if I'd select any option to load a kernel or type any command that would load a kernel, then all that would happen was that the kernel would print one backslash and then hang. This problem was caused by the fact that GRUB selected a graphic instead of a text-based terminal mode. Using this stanza, GRUB switches to a text console just before booting FreeBSD and it all boots just fine:

title FreeBSD 6.0
terminal console
root (hd0,3,a)
kernel /boot/loader

Making Firefox and Sylpheed play nicely together

Just a reminder; this has been covered extensively elsewhere on the web. In order to let Sylpheed Claws and Mozilla Firefox play nicely together, you need to fiddle a bit with some settings here and there. (Doing this for regular Sylpheed is very similar and left as an exercise.)

First create two scripts, say inside the subdirectory of your home directory called bin; call one mailto.sh:

# mailto.sh
exec sylpheed-claws --compose "$1"

and the other firefox-open.sh:

# firefox-open.sh
if firefox -remote 'ping()' 2> /dev/null ; then
exec firefox -remote "openurl($1, new-tab)"
exec firefox "$1"

Then make both executable (with chmod a+x ~/bin/*.sh). Now in Sylpheed Claws, select Configuration, Preferences, External Programs. Put /home/epostma/bin/firefox-open.sh "%s" into the Web browser field. (Change /home/epostma into your home directory.) Then in firefox, visit the URL about:config. On the line that says Filter, input network.protocol-handler. You should have about a screenful of settings now. Check that network.protocol-handler.external.mailto is set to true (if not, double click). Now check if there is a setting called network.protocol-handler.app.mailto: if no, right-click and select New - String and create it. Then set it to the value /home/epostma/bin/mailto.sh (again, substitute your home directory for /home/epostma).

Now clicking on a mailto:-link in Firefox should open Sylpheed and clicking on a URL in Sylpheed should open Firefox (a new tab if it was already open and a new window otherwise).

Resizing an LVM2 partition with a ReiserFS file system on it

I use the following to safely resize my LVM2-partitions containing Reiser file systems. Safely means I don't need to be afraid of cutting pieces of my filesystem when shrinking the partitions. The trick is to use resize_reiserfs without argument to let it fill all of the available partition. The following assumes you want to move some space from /home to /var, which correspond to the logical volumes home and var, respectively; both in the volume group vg0. Of course it's best to do this in single user mode. If you use a filesystem that allows online resizing, you don't need to do that, I guess.

umount /home /var
resize_reiserfs -s -11G /dev/mapper/vg0-home
lvreduce -L -10G vg0/home
resize_reiserfs /dev/mapper/vg0-home
vgdisplay vg0 | grep Free
# Note number of free PEs:
# Free PE / size: 2816 / 10.00 GB
# You can also just say lvresize -L +10GB
lvresize -l +2816 vg0/var
resize_reiserfs /dev/mapper/vg0-var
mount /home
mount /var

My GreaseMonkey script for the GAP web site

There is an extension for the open source web browser FireFox named GreaseMonkey. It does an amazing job at letting you customize web sites you frequently visit. Note that this requires nothing on the part of the web site administrator; it all happens inside the browser.

One of the sites I frequent rather often is the index of the manual of GAP, a computer algebra program I use a lot. I tend to use Type Ahead Find to find the page I need. This selects the text next to the link I'd like to visit, but I cannot just press Enter: the text is not in the "active" part of the link. I created this GreaseMonkey-script: gap-typeahead-script.user.js. It extends the link so that the text is active, too. You need the GreaseMonkey to activate it.

A previous version of the script was created using, additionally, the Platypus extension. I don't know why, but it stopped working when upgrading the browser version. So I decided to look at Dive Into GreaseMonkey in order to learn how to write it myself. I really like the book; it's by Mark Pilgrim of Dive Into Python fame.

Exim's picky Sieve script engine

I've written a Sieve script for delivery of my email messages to different folders. Exim, the standard Debian mail transfer agent, is rather picky about how you write the arguments to fileinto if you use the maildir format: you have to use the actual absolute path in the filesystem. E.g., to put a message into your logs folder, write

  fileinto "/home/epostma/Maildir/.logs/";
if /home/epostma is your home directory and your maildir hierarchy is under the Maildir hierarchy. I think the slash at the end is necessary, but I'm not quite sure.

OpenSSH public key permissions

When using the OpenSSH server, if you want to log in remotely using a public/private key pair, there are many requirements on the permissions of files and directories. One that is relatively badly documented (and that bit me once) is that the home directory of the user on the server needs to have permissions 755, not 775.

Compiling kernels the Debian way

I almost always look it up here. I patch my kernels with the exec-shield patch by Ingo Molnar; I tried GRSec/PaX, but I’m too stupid to get it to work without investing too much time. I have the sticky bit and world writable permissions on /usr/src set, so that I can unpack the archive and work in it unhindered by permission problems yet with others unable to damage the kernel source directories.

aptitude install linux-source-2.6.x
cd /usr/src
tar xvjf kernel-source-2.6.x.tar.bz2
cd kernel-source-2.6.x
make mrproper
patch -p1 < ~/downloads/exec-shield-nx-2.6.x.patch
make mrproper
cp ../kernel-source-2.6.(x-1)/.config .
make oldconfig
make gconfig
make-kpkg clean # necessary because of --revision
make-kpkg --rootcmd fakeroot kernel_image --revision 1 --append-to-version -execsh-1
sudo mount /boot -o rw,remount
sudo dpkg -i ../kernel-image-2.6.x-execsh-1_1_i386.deb
sudo mount /boot -o ro,remount

With modern versions of make-kpkg, this updates the grub file.

Getting DRI running on an i810

To get DRI running on an i810, you need to set defaultdepth to 16 in your Xorg.conf or XF86Config-4 or similar.

The mozilla refresh policy

It’s happened more than once that I had trouble finding this: in mozilla and family, the refresh policy is to be found in about:config, key browser.cache.check_doc_frequency. The meaning is as follows:

0 Once per session
1 Every time I view the page
2 Never
3 When the page is out of date (this is the default)
For more stuff like this: see http://www.mozilla.org/quality/networking/docs/netprefs.html.

A Mozilla / Firefox keyword for the Dutch telephone directory

I just love Mozilla / FireFox Keywords. If you use one of those browsers and if you live in the Netherlands, do the following:

  1. Bookmark this piece of javascript:

    That means, right click on the link and click ‘Bookmark this link...’, then enter a name for the link (e.g., ‘Telefoongids’) and choose a folder where to save this bookmark. You will only need to click it once, so it need not be an easily accessible folder. I have a special folder for Keyword links.
  2. Left click on the Bookmarks menu item, select the folder you put the link into, right click on that link and select Properties.
  3. Type the keyword that you’d like to use, e.g. tel, into the box labelled Keyword.
  4. Click OK.
Now if you want to have the phone number of, say, Mr. Meijer in Amsterdam, you type tel meijer amsterdam into the address bar of the browser and it takes you to the phone book page of all people called Meijer in Amsterdam (there are about 1200 of them). If you only type a name, you get the people in Eindhoven called that (to change this, edit the properties of the link again, scroll through the url until you find the text eindhoven and change it into your favourite city name).
This is an adaptation of a script on a mozillaZine page that has it from a bugzilla page again. Note that this does not yet work if you are looking for Mr. De Vries or for someone in The Hague, because there are spaces in both those names. If you type tel "de vries" "den haag" the script understands that, but the web server does not understand the way the script tries to say it. Please email me if you've solved this!

Having both WebDAV access and being able to hotcopy a Subversion repository

I use the Subversion version control system for a couple of things. Every night I make a backup of the repository to a remote server, having hot-backup.py run by a user in the svnusers group without further privileges. So all files in the repositories should be group readable and writable. This is relatively easy to accomplish for local and svn+ssh users with the Subversion book. However, for access via WebDAV there are more steps and they're not so easy to find out:

  • Change group ownership of all files in the repository to svnusers.
  • Set the SGID permission bit on the dav/, db/ and locks/ directories, so new files will also be owned by svnusers.
  • Run apache httpd with the mod_umask module. It's undocumented, but reasonably simple. First install it (it's not part of a standard apache install). This may entail compiling from source. Then just put
        LoadModule umask_module /usr/lib/apache2/modules/mod_umask.so
    and umask 0017 somewhere in your httpd.conf (or if you're so lucky as to be running Debian, use the tricks by them: add the LoadModule to a new file in mods-available and the umask to the file in sites-available that takes care of your Subversion repository, then enable them).

Of course, now you still need to enable SSL to make it secure...