2013/12/16

Non-exhaustive checklist of signs you have failed your Christmas decorations

If you meet any of the following conditions, you have failed:

Your lights are all one colour

You might think that uniform colours look really IN and DESIGN. I think uniformity is contemptable and that designers need to relearn their colour charts. Seriously, guys, there are more colours out there then white, grey and black.

You have blue lights

The blue lights that came out a few years ago are the colour of death. Where Christmas lights are normally gay fun things, the blue lights suck fun out of your hearts, leaving only sorrow and loneliness.

You only have blue lights

What are you, a 16 year old goth girl who thinks all life is suffering and misery? Did you hire a Dementor to do your decorations?

Your lights are flashing

I could go with an epilepsy joke here but it isn't fit. What I hate about flashing lights is that they aren't random. They have a steady duty cycle, but each controler has a different duty cycle. This means every once 4-5 minutes or so they all sync up and this distracts me to no end.

Your lights imitate icicles

Not only because they are probably all white, but also because real icicles are an annoying sign your roof insulation needs to be fixed.

You don't have enough lights

A half-assed effort looks half-assed. Is half a Christmas going to be fun? Half a Christmas tree? Half of the plum pudding? Half the bottle of rum? OK, so that last one would be fun. At least until the next morning.

You have far to many lights

Even if having your front lawn as bright lit as a prison yard pleases you, please think of our telescopes, vital to the national interest and how light pollution is rendering them useless.

2013/12/13

Fun with perl

Want to help me out? Run the following code:
#!/usr/bin/perl

use strict;
use warnings;

use Data::Dump qw( ddx );
BEGIN { ddx "DIE=", $SIG{__DIE__}; };
use Test::More tests => 1;
BEGIN { ddx "DIE=", $SIG{__DIE__}; };

diag "Perl: ", sprintf "%vd", $^V;
diag "Test::More: $Test::More::VERSION";
pass "one test";

What do you expect $SIG{__DIE__} to contain? Acceptable answers are undef, "" and "DEFAULT". And the answer varies according to what version of perl and what version of Test::More you are running.

Example output:

# DIE=""
1..1
# DIE=sub { "???" }
# Perl: 5.004_05
# Test::More: 0.47
ok 1 - one test
# die:7: ("DIE=", undef)
1..1
# die:9: ("DIE=", "")
# Perl: 5.8.8
# Test::More: 1.001002
ok 1 - one test
# die:7: ("DIE=", undef)
1..1
# die:9: ("DIE=", undef)
# Perl: 5.10.1
# Test::More: 1.001002
ok 1 - one test
1..1
# -:9: ("DIE=", undef)
# Perl: 5.16.2
# Test::More: 1.001002
ok 1 - one test

And yes, I know 5.004 dates from the previous century.

No fun

Trying to get Percona Server 5.6 to work with SphinxSE 2.1.2 was no fun. First off, it used to be that SphinxSE would create a load of .so .la, .a files. Now it just needs ha_sphinx.so. Second off, you have to execute INSTALL PLUGIN sphinx SONAME 'ha_sphinx.so'; This requires grant tables to be on (I generally have them off because it's less trouble and I have networking turned off in MySQL anyway, unless I have replication going). At least this is saved into mysql.plugin so I don't have to do it each time I restart mysqld.

And then, when I get it all set up, I get the following error

ERROR 1429 (HY000): Unable to connect to foreign data source: failed to resolve searchd host (name=localhost)

I'm WTFing just about as hard as I can right now. localhost is in /etc/hosts. It is also in my DNS server. Has MySQL gone insane? Percona? I'll blame Oracle, because they are just mean.

The solution, of course, is ALTER TABLE sphinx CONNECTION='sphinx://127.0.0.1:9312/YCUR';.

2013/10/03

This is what the big boys call uptime.

~ (fil@billy:)$ uptime
 16:07:57 up 1064 days, 16:08,  1 user,  load average: 0.02, 0.06, 0.08
Close to 3 years !

2013/09/19

Taxes and programming.

Just a short and silly note to point out that Canada no longer has piggy-backed sales taxes. PEI and Québec used to calculate provincial sales taxes on the sub-total of sale + the GST (hence the term piggy-back). This led to annoying special code. Well, annoying to programmers at least.

But Québec moved to PST+GST on the January 1st 2013, and PEI moved to HST on April 1st, 2013.

2013/07/01

World's smallest chat

I was goofing around and someone set up a Linux VM and invited everyone to log in over ssh. I think his goal was to make a bullet-proof Linux setup. Something that would withstand users deliberately trying to bring the computer down.

BTW, the world's smallest formbomb is

:(){ :|:& };:
But you protect against it by putting soft and hard limits on the number of processes via limits.conf.

Anyway, back to the fun and games. The admin had removed wall (for obvious reasons) and didn't have a talkd. This meant we couldn't talk to each other. So I cooked up the World's Smallest Chat.

In one window, you start the chat with

echo "First line of chat" >/tmp/chat
chmod og+rw /tmp/chat

Then in another window:

tail -F /tmp/chat

Everyone can post to the chat with

echo I don't think so >/tmp/chat

However, anyone can DOS the chat with

yes >>/tmp/chat

But given how this is a chat in 4 lines of code, I don't see that as being a problem.

2013/05/22

Breaking news

The new CPU means that Corey is now fast enough to play CBC.ca/sports HD hockey stream full screen, at 27 inches. This is a huge change from the postage stamps I had when I first started watching streaming hockey.

To bad Ottawa is being blown away by Pittsburg.

I need more power!

I upgraded Corey again. This time with a brand-new used CPU. I require Corey to be fanless. This means I can't use the most advanced CPU out there. High end CPUs get far to hot, even for my massive heat sink. The advantage of this, though, is that I got the CPU off eBay for a fraction of the cost of something new. The previous CPU was an LE-1100 and had a thermal design of 45W. I could have gotten a 2 core CPU with a thermal design of 65W but I was afraid of overheating. I got an LE-1660, still 45W but 47% faster then the previous CPU.

Anyway, it arrived today. And instead of working, I installed it. This was a bit of an adventure. This CPU didn't exist when my motherboard was built, so while it booted, Linux was showing the CPU ID as "unidentified" which was disconcerting. I decided to upgrade the BIOS. Which is where our adventure begins.

ASUS provides a BIOS flashing utility for DOS. When was the last time you booted DOS? I have some DOS floppies... but that way lies pain. How about booting DOS from a USB key? With a little farting around, here is what I discovered.

First off, my USB key is already formatted with one partition, FAT32. It is /dev/sdb on my system.

yum upgrade syslinux # just in case
sudo syslinux -f /dev/sdb1
# This next command is so non-obvious the developers should be shot!
# Why isn't this integrated into syslinux?
sudo dd conv=notrunc bs=440 count=1 if=/usr/share/syslinux/mbr.bin of=/dev/sdb
sudo mount /dev/sdb1 /mnt
wget http://goebelmeier.de/bootstick/bootstick.zip
unzip bootstick.zip 
cd BootStick/
sudo rsync -av usb-root/ /mnt/ # ignore the permission warnings
cd ..
unzip AFUDOS236.zip
sudo cp AFU236U.exe /mnt/flash/afu.exe
unzip M2NSE501.zip
sudo cp M2NSE501.ROM /mnt/flash/

Now reboot from the USB key. For me, this involves hitting F8 inside a 5 second window. Type ENTER twice when DOS asks for time and date. Then

CD FLASH
AFU /O0308.ROM 
AFU /IM2NSE501.ROM
The first AFU command saves the current ROM. The second one flashes with the new ROM. It takes a tense 2 minutes for it to complete. Tense because I realized to late the computer wasn't plugged into a UPS. A black out during ROM flashing means a bricked motherboard.

Of course, flashing a new ROM means all BIOS config is reset to annoying factory defaults.

What's more, this new BIOS will not boot Linux without noapic. But with only one core, I don't really care. I turned the APIC off in the BIOS.

So, was it worth it? Subjectively Corey feels a lot faster. And hotter; when Corey was lying flat on the test bench, the heat sink was almost to hot to touch. CPU temp was 59C! Now with Corey upright, CPU temp is 51C. Given that the max operating temp is 65C, I wonder if it can survive the next heatwave. What's more, the new CPU has virtualization instructions, so I can run KVM on my desktop!

2013/04/17

CentOS X .xsession

Further annoyances with CentOS 6. It now uses .xsession as the last resort. The work around is to add the following lines to /etc/X11/xinit/Xsession. Put them just after the line that sources /etc/X11/xinit/xinitrc-common

if [ -x "$HOME/.xsession" ]; then
    exec -l $SHELL -c "$CK_XINIT_SESSION $SSH_AGENT $HOME/.xsession"
fi

Yes, there's probably a smarter way of doing it. But I don't want to bother tracking it down.

CentOS 6 X problems

First off, 6.4 came out and I didn't notice.

Second off, while setting up my new Laptop (Nicko, an IBM t61) for development, I managed to mess up Xorg. The error messages are

[ 25469.587] [dix] Could not init font path element catalogue:/etc/X11/fontpath.d, removing from list!
[ 25469.587] [dix] Could not init font path element built-ins, removing from list!
[ 25469.587] 
Fatal server error:
[ 25469.587] could not open default font 'fixed'

A quick fix is just yum -y upgrade. But given this would push me to 6.4 (aka a lot of downloading), a smaller fix was required. I found the following got the job done. I strongly suspect the libXfont is all that is required. YMMV

wget ftp://ftp.muug.mb.ca/mirror/centos/6.4/os/x86_64/Packages/xorg-x11-drv-modesetting-0.5.0-1.el6.x86_64.rpm
sudo rpm -Uvh xorg-x11-drv-modesetting-0.5.0-1.el6.x86_64.rpm
sudo yum install pixman pixman-devel libXfont -y
sudo yum groupinstall Desktop -y

2013/03/11

Affordance, discoverability and death to the scroll bar!

There has been a lot of drama lately about major changes to the UI of some popular OSes. A lot of this drama can be boiled down to It's different! It takes me out of my comfort zone! But of course nobody is honest enough to say that straight out. Instead they will claim the UI is not intuitive.

Claiming an interface is intuitive (or not) is a red flag for me. It is unlikely that anyone using the word knows much about UI (and UX and IX), for the simple reason that there is no such thing as an intuitive interface. All interfaces must be learned, including how to suckle a mother's breast.

Features of an interface that can be quantified are discoverability (how easy it is to learn) and affordance (how easy it is to use).

We will start with affordance; it basically measures how easy one element of the UI is to use (eg, click) relative to surrounding elements. Concretely, bigger things are easier to click on then smaller things; things at the edge of the screen are easier to mouse over then things towards the center.

One example of affordance nightmares are the up and down (left/right) arrows of scroll bars, compared to using the gutters for (pretty much) the same purpose. (Visual guide to the scroll bar to your right, my left) The arrow buttons are small, on the order of 12x12 = 144 pixels on a screen that is 1920x1080=2073600 pixels. It is hard to get your mouse over them to click. And all that effort is rewarded by moving the text by a mere 30-40 pixels. (On a side note, a sure way to drive me nuts is to scroll through a page by repeatedly clicking on the down arrow.)

Compare the uselessness of these arrows to the gutters that are right below (or beside or above) the arrows. First, by being long (if narrow) and on the edge of the screen, they are relatively easy to hit (unless the content nearly fits in the window, in which case they are useless). And they reward you by moving the content of the window by roughly the height of the window; what was at the bottom of the window should now be at the top.

But of course scroll bars are pretty much obsolete. The page up/down keys, the space bar (in browsers) and most importantly the mouse wheel are all have much higher affordance. The scroll bar can be reduced to a line within a line, representing the current position within the full content of the window. This is the case in Android on my Nexus 7, even though the screen is a whopping 1280 x 800 pixels. Compare this to the VGA 640x480 pixel screens that used to be wide spread. We ran Windows 3.11 on those computers, and had massive 8-pixel scrollbars (1.25% of the screen width). 16-bit windows also had a bug in that if the content was large enough, the slider would be reduced to just a few pixels high (or wide), dropping its affordance close to zero.

On to discoverability; this is a measure of easy it to find out how to do something. Common things should be easy to discover but it should still be easy to discover rare things. Android 4.2 on my Nexus is a joy in this regard. I assume the other phone/tablet OSes are similarly as good.

You can poke at anything on the screen. "Hey look, a little bluetooth logo, I want to turn that off. [poke] [poke] Hey look! I just drew down a window that contains the 3 pieces of commonly used information (user, WiFi SSID, battery charge), 4 of the commonly adjusted settings (airplane mode, bluetooth, auto rotate, brightness) and a button to get to the settings app.

And because pretty much nothing looks like a traditional button everything could be a button. Poke it and find out!

The traditional menu bar is something of a discoverability nightmare. Pretty much every function of the application gets stuffed in a menu or sub menu. There are so many that people never explore what they do. They've learned to locate the 5 functions they need to get their work done and ignore the rest.

2013/03/07

Firefox "upgrade"

If you are upgrading to Firefox 18, 19 or newer on a slightly older system (say Ubuntu 10 LTS), you will see the following error message :

libxul.so: undefined symbol: _ZNSbItN4base20string16_char_traitsESaItEE4_Rep20_S_empty_rep_storageE

The solution is to use Firefox 17.0ESR. It's a better version anyway.

Ideally you will also make your displeasure known to the idiots at Mozilla

2013/02/19

PAR Wins!

New client, they set up a SuSE Enterprise Linux VM for me to install on. I approach this with trepidation. SLES is distinct from OpenSUSE, so I can't set up a VM at home for staging. Turns out my fears were misplaced; a PAR built on CentOS 5.8 runs on SLES 11.2 with only a minor problem. Colour me Impressed.

The minor problem was that some libraries aren't the same version. But a simple -l db -l gnutls -l gnutls-extra -l gnutls-openssl works around this. Of course, PAR::Packer only looks in LD_LIBRARY_PATH for libraries. MUST NOT BE SIDETRACKED INTO FIXING THIS.

Here's how to check shared libraries. First you build your PAR. Then extract it:

mkdir t
cd t
unzip ../your.par

Now scan that with the following code:

#!/usr/bin/perl

use strict;
use warnings;

use File::Finder;

my %already;
foreach my $lib ( File::Finder->name("*.so")->in('lib') ) {
    foreach my $line ( qx(ldd $lib) ) {
        chomp( $line );
        next unless $line =~ /(.+)\s+=>\s+(.+)\s\(0x/;
        my( $so, $file ) = ( $1, $2 );
        next if $file =~ m(^/lib);  # assume anything in /lib and /lib64 are OK
        next if $already{$file}++;
        print "rpm -qf $file # $lib\n";
    }
}

This will produce some commands that you then paste into a command prompt on the remote computer. If one of the lines doesn't show up, you will have to include it in the PAR. Note that sometimes one distro will put the library in /usr/lib64 and another distro will put it in /lib64 which might cause false negatives. I wonder what the overhead of including EVERY library in the PAR would be. MUST NOT BE SIDETRACKED.

2013/02/12

Installing fonts in CentOS

This is here because I keep forgetting:
fc-cache /path/to/fonts
. Also, under CentOS 6:
yum install dejavu-lgc-sans-mono-fonts \
 dejavu-sans-mono-fonts \
 gnu-free-mono-fonts \
 google-droid-sans-mono-fonts \
 liberation-mono-fonts \
 oflb-smonohand-fonts

2013/02/07

cups-lpd and syslog

cups-lpd logs everything to syslog. This fills up /var/log/messages unnecessarily. I finally pulled out the source code and went about writing a patch so that it logs to a file. And then someone on #cups indirectly pointed out that cups-lpd uses LOG_LPR faculty and syslog can filter with these. The trick is these 2 lines in /etc/syslog.conf
*.info;lpr.!info;mail.none;news.none;authpriv.none;cron.none        /var/log/messages
lpr.*   /var/log/cups/cups-lpd_log
The first one sends *.info, EXCEPT lpr.info to /var/log/messages. The second one sends lpr.* to /var/log/cups/cups-lpd_log. Note that this means that any other program that uses LOG_LPR will also log to the same file.

But that's not all; xinetd also logs to syslog. But it can be easily convinced to log to a file, with the following /etc/xinetd.d/cups-lpd:

service printer
{
    disable = no
    socket_type = stream
    protocol = tcp
    wait = no
    user = lp
    server = /usr/lib/cups/daemon/cups-lpd
    server_args = -o job-sheets=none
    log_type = FILE /var/log/cups/cups-lpd_log
}
So there you have: how to prevent cups-lpd from logging to syslog.

2013/02/03

Cogceco, you impress me

I got some postal mail from Cogceo. I thew it on the passenger seat and thought to myself "bet they are offering me a new, extra fast extra expensive bandwidth package." Because the cost of ISPs only ever goes up, unlike the cost of computers or the cost of renting a server, etc. Because there is zero competition amongst ISPs; for broadband I can have DSL or DOCSIS, provided by Bell or Cogeco. Both have resellers, but the basic rate is fixed by Bell or Cogeco. But I was wrong. The letter was to announce improved service (upload speed doubling) but not a rate increase. Yet.

2013/01/30

All the little houses falling over just right

To boot CentOS 5, all the following needs to be set up and running BEFORE you reboot your computer.

  1. GRUB installed on the boot drive (aka sda, ata1, sata1);
  2. a /boot that grub can find and read. In particular, it must be small and at the front of the boot drive;
  3. a kernel+initrd that contains the drivers to find and mount the final root filesystem (aka /); this can involve swearing, repeated applications of mkinitrd. At worse, you can pull initrd apart with gzip+cpio, add the drivers, modify init and repack it. Note that this is not a shell script but a nash script. CentOS 6 has moved to dash;
  4. a / that has a working init and all that entails (obviously);
  5. an /etc/fstab that won't fail out because fsck -A can't find a drive or partition. If you've moved / to another partition or to LVM, then you need to update fstab. You can set the last 2 columns to 0 if you don't want fsck to check that mount.

2013/01/29

Booting from a ghost partition

The most insane things can happen. Booting a new kernel, you see it in /boot/grub/grub.conf, but you don't see it in the GRUB menu at boot time. This has happened to me twice recently. First time, I lost 2 hours and thought I was going mad before I figured it out.

The cause is that I have /boot as a software RAID (/dev/md0, raid1 of sda1, sdb1, sdc1). While GRUB supports Linux software RAID1, it only does so partially; it assumes that the first drive of the array is the same as the others and uses it as an ext3 (or other) partition. What had happened a few weeks back was that sda1 had become the spare drive. This was caused by a mislabeled ICY DOCK; what I thought was sda became sdc, and sdc, sda. This first time I gave up before figuring it out, copied /boot into a temp directory, reformatted sda1 as a straight ext3 and copied /boot back into it.

This second time, I had already seen it and new where to look. That is /proc/mdstat. And to make sure that sda1 was an active part of the array. Sure enough, sda1 wasn't even in the array! So

mdadm /dev/md0 --add /dev/sda1
Then wait a minute for the RAID to rebuild, reboot and everything was fine.

This particular array had 3 active drives, no spares. I had replaced sda at some point and while I had added it to the main array (md1, raid5) I hadn't done so for md0. Why does md0 have no spares? It seemed like a good idea at the time. Repairing a computer that won't boot is annoying. Having all active, no spares means you never (in theory) end up with a disk that won't, should the first one give up the disk. And given that /boot is only written to once every blue moon, so it's not like I'm stressing the spare at all.

In the second case all 3 partitions of md0 are active; there are no spare drives. Had it been a case like first one, I would have forced sda1 to be an active partition in the array. Something like

mdadm /dev/md0 --fail /dev/sdc1 # cause the array to rebuild to sda1+sdb1
# now get sdc1 as the spare
mdadm /dev/md0 --remove /dev/sdc1 
mdadm /dev/md0 --add /dev/sdc1

2013/01/25

And now for something silly

I've mentioned Gunilla before. Here is a small Perl program, based on code by Yaakov.

Usage :

set-message
Sets the message on default printer to "Insert Coin"
set-message something
Sets the message on default printer to "something"
set-message 10.0.0.12 "Hello World"
Sets the message on printer at 10.0.0.12 to "Hello World"

I made my life harder (of course) by supporting \n. To do this, the program needs to know the width of your display ($WIDTH). Adding something like ~/bin/gunilla $(date +%A\\n%Y/%m/%d) to a crontab might be useful.

#!/usr/bin/perl

use strict;
use warnings;
use IO::Socket;

# Configuration:
my $WIDTH = 16;
my $peeraddr = 'gunilla';

my $rdymsg;
if( @ARGV == 0 ) {
    $rdymsg = 'Insert Coin';
}
elsif( @ARGV == 1 ) {
    $rdymsg = $ARGV[0];
}
elsif( @ARGV == 2 ) {
    ( $peeraddr, $rdymsg ) = @ARGV;
}
else {
    die "usage: $0 [] [\"\"]\n";
}
 
$rdymsg =~ s{^(.*)(\n|\\n)}{newline($1)}e;

my $socket = IO::Socket::INET->new(
        PeerAddr  => $peeraddr,
        PeerPort  => "9100",   
        Proto     => "tcp",    
        Type      => SOCK_STREAM
    ) or die "Could not create socket: $!";

my $data = <<EOJ;
\e%-12345X\@PJL JOB
\@PJL RDYMSG DISPLAY="$rdymsg"
\@PJL EOJ
\e%-12345X
EOJ
   
print $socket $data;

sub newline
{
    my( $text ) = @_;
    my $l = $WIDTH - length $text;
    $l = 1 if $l < 1;
    return $text. ( ' ' x $l );   
}